限制线程访问给定的块代码

时间:2012-10-30 21:48:26

标签: java multithreading

我最近使用的是Java Threads,我正在尝试实现一种能够将一段代码限制为仅由一个线程执行的方法,让我们称之为“单一”。

我已经实施的一个天真的解决方案如下:

if(readFlag())
{
  synchronized(this)
  {
  flag = false;  
  // do some work
  }
} 

其中:

public Boolean synchronized readFlag() {return flag;}

这种天真的解决方案仅适用于一个“单个”块,但是当我尝试使用多个“单个”代码块时会出现问题。由于我不能使用相同的标志,因为不同的线程可能同时输入不同的“单个”代码块。

另一个解决方案可能是为每个“单个”使用一个标志变量数组,但是这个解决方案在循环内部执行“单个”代码块时会遇到问题(或需要使用障碍),旁边不是非常灵活

我的问题是:

如何改进此解决方案以允许执行各种“单个”代码块并允许多次执行相同的单个代码块(例如,循环内的单个代码块)。

2 个答案:

答案 0 :(得分:4)

您可以更改同步的对象。除非您需要,否则无需在this上进行同步。如果你有两个需要同步的块但是可以同时执行(每个只有一个线程),你可以做类似的事情

private final Object lock1 = new Object();
private final Object lock2 = new Object();
...
synchronized(lock1) { // do stuff. the code in lock2 can be executed while another thread is executing this }
synchronized(lock2) { // do stuff. the code in lock1 can be executed while another thread is executing this }

另请查看ReentrantReadWriteLock以获得更复杂的锁定(允许多个读者但只允许一个编写者)。

答案 1 :(得分:3)

过去几天我遇到过类似的问题。 在我的情况下,我必须在ConcurrentMap中执行清理任务,并且每10分钟只有一个线程应该执行该任务。我没有必要同步,因为ConcurrentMap迭代器保证不抛出ConcurrentModificationException。 为了确保只有一个线程执行清理任务,我使用了AtomicBoolean:

AtomicBoolean flag = new AtomicBoolean(false);
...

boolean proceed = flag.compareAndSet(false , true);
if(proceed){
   doStuff();
   flag.set(false);
}

因此,这可以避免在布尔标志上进行同步。根据要同步的不同代码段,我同意Jeff ..您可以同步不同的对象。