我几乎阅读了与我的问题相关的所有帖子,但无法解决我的问题。这段代码是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();
}
}
}
答案 0 :(得分:4)
锁不起作用,因为ReentrantLock是WordCount类中的实例变量。因此,该类的每个实例都有自己的私有锁,并且它们不会相互同步。最容易的变化是使锁定静态,就像它保护的变量一样。
答案 1 :(得分:2)
每个Runnable
都有自己的锁定对象。为了使您的策略有效,他们都需要完全分享一个锁。
例如,
// ...
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));
// ...
}