【问题标题】:Multithread programming and incrementing a static variable多线程编程和增加静态变量
【发布时间】:2015-07-23 20:54:19
【问题描述】:

我已阅读几乎所有与我的问题相关的帖子,但无法解决我的问题。此代码是 Big Java - Cay Horstmann 的早期对象中的一个问题。该问题询问有关使用多线程编程计算几个文件的单词并存储组合单词计数这是我的问题。

为了获得组合计数器,我使用了static 变量,该变量在线程中计数单词的每次迭代中递增。此外,我使用ReentrantLock() 使增量一次只能用于一个线程。 一切正常,除了递增。有时静态变量似乎没有增加。我测试了lock()unlock()的数量 通过每个线程,它们与我的预期结果相匹配,但是 static 变量无法正常工作。

有什么解释吗?感谢您的时间和帮助。

我的task class:

 import java.io.File;
 import java.io.FileNotFoundException;
 import java.util.Scanner;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;

public class WordCount implements Runnable
{
    private String fileName;
    Scanner inputFile;
    private long counter;
    public volatile static long combinedCounter = 0;
    Lock ccLock;

    public WordCount(String aName) throws FileNotFoundException
    {
        try
        {
            this.ccLock = new ReentrantLock();
            this.counter = 0;
            this.fileName = aName;
            this.inputFile = new Scanner(new File(this.fileName));
        }
        catch (FileNotFoundException e)
        {}
     }
    public void cCount()
    {
        ccLock.lock();
        try
        {
            combinedCounter++;
            /*synchronized (this)
            {
                combinedCounter++;
            }*/
         }
        finally
        {
            ccLock.unlock();
        }
     }
    @Override
    public void run()
    {
        try
        {
            while (inputFile.hasNext() && !Thread.interrupted())
            {
                 synchronized (this)
                 {
                     cCount();
                 }
                 counter++;
                 inputFile.next();
                 Thread.sleep(0);
             }
             System.out.printf("%s: %d\t\t%d\n", this.fileName,           
             this.counter,combinedCounter);
        }
         catch (InterruptedException e)
         {}
     }
 }

这是我的client class

    import java.io.FileNotFoundException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;

    public class WordCountRunner
    {

        public static void main(String[] args) throws FileNotFoundException,
                InterruptedException
        {
            String a = "a.txt";
            String b = "b.txt";
            ExecutorService pool = Executors.newFixedThreadPool(2);
            ;
            try
            {
                Runnable r1 = new WordCount(a);
                Runnable r2 = new WordCount(b);
                pool.execute(r1);
                pool.execute(r2);

                while (!pool.isTerminated())
                {
                    pool.shutdown();
                }
                Thread.sleep(100);
                System.out.print("***" + WordCount.combinedCounter);
            }
            catch (FileNotFoundException e)
            {

            }
            finally
            {
                pool.shutdown();

            }
        }

    }

【问题讨论】:

  • 运行所有这些线程的程序部分在哪里?顺便说一句,我认为您应该在每个线程中私下计算,然后将 result 添加到组合数据中。
  • 为什么不直接同步静态变量,不用担心锁...
  • 我添加了客户端类@RealSkeptic。我现在正在检查您的解决方案。
  • 我正在检查它@brso05 - 没用。
  • 如果您使用的是 Java 8,请查看 LongAdder

标签: java multithreading static locking


【解决方案1】:

锁不起作用,因为 ReentrantLock 是 WordCount 类中的一个实例变量。因此,该类的每个实例都有自己的私有锁,并且它们彼此不同步。最简单的更改是使锁成为静态的,就像它所保护的变量一样。

【讨论】:

  • 应该Lock 总是static 吗?还有其他解决办法吗?
  • 我建议了最简单的更改。 Lock 对象应该与它所保护的对象具有相同的对象生命周期。意思是,它与它保护的对象同时被创建和销毁。但是,有多种方法可以解决这个问题。例如,正如@brso05 提到的,您可以在静态变量上简单地synchronize 并达到相同的效果。
【解决方案2】:

您的每个Runnables 都有自己的锁定对象。为了使您的策略发挥作用,它们都需要完全共享一个锁。

例如,

    // ...
    static Lock ccLock = new ReentrantLock();

    public WordCount(String aName) throws FileNotFoundException
    {
        try
        {
            // this.ccLock = new ReentrantLock();
            this.counter = 0;
            this.fileName = aName;
            this.inputFile = new Scanner(new File(this.fileName));
        // ...
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-15
    • 2012-01-15
    • 2013-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-24
    相关资源
    最近更新 更多