同步:线程以相同的顺序执行两个关键部分

时间:2015-09-02 12:32:43

标签: java multithreading concurrency semaphore synchronisation

我有以下类型的代码:

synchronized block1 {
    //only one thread in the block
}

{lot of code where synchronization not necessary}

synchronized block2 {
    //only one thread in the block. 
    //All the threads that executed block1 before this thread should have already executed this block.
}

每个线程首先以相同的顺序执行block1,非同步块和block2。

如果线程T1在线程T2之前执行block1,那么T1应该在T2之前执行block2。有两个以上的主题。

有没有办法在java中实现这个目的?

4 个答案:

答案 0 :(得分:2)

这基本上创建了一个队列,线程将等待,直到它们的数量出现。 [增订]

private AtomicInteger place = new AtomicInteger(0);
private AtomicInteger currentPlaceInQueue = new AtomicInteger(0);
private ReentrantLock lock = new ReentrantLock();
private Condition notNext = lock.newCondition();

public void method() {

   ThreadLocal position = new ThreadLocal();

   synchronized(this) {
      //Your code
      position.set(place.getAndIncrement());
   }

   // More code

   lock.lock();
   while ((int) currentPlaceInQueue.get() != position.get()) {
      notNext.await();
   }
    // More code
   lock.unlock();
   currentPlaceInQueue.getAndIncrement();
   notNext.notifyAll();
 }

答案 1 :(得分:2)

据我所知,关键部分#2必须按照与关键部分#1相同的顺序执行

  

如果线程T1在线程T2之前执行block1,那么T1应该在T2之前执行block2。有两个以上的主题。

然后可以使用队列来确保执行顺序。

private Object lock = new Object();
private Queue<Thread> threadQueue = new ArrayDeque<>();

// https://stackoverflow.com/questions/32353283/synchronization-threads-execute-two-critical-sections-in-same-order
public void executeCriticalSectionsInOrder() throws InterruptedException {
    // Critical Section #1
    synchronized (lock){
        // synchronized code #1

        // Add self to queue
        threadQueue.add(Thread.currentThread());
    }

    // {lot of code where synchronization not necessary}

    // Critical Section #2
    synchronized (lock) {
        //All the threads that executed block1 before this thread should have already executed this block.
        // Wait turn
        Thread t = threadQueue.element(); // Do not remove until it is self
        while (t != Thread.currentThread()) {
            lock.wait();
            // After sleep try again
            t = threadQueue.element();
        }
        // Verified own turn. Update status
        threadQueue.remove();

        // synchronized code #2

        lock.notifyAll(); // Awake any waiting thread after exiting section.
    }

然而如果一个线程在没有从队列中删除自己的情况下死亡/退出,那么后续线程将被无限制地阻止。也许添加一个finally块来做家务管理?

注意:在Nicholas Robinson's answer中,建议使用排名顺序而不是排队,这看起来效率稍高。

答案 2 :(得分:0)

示例中的synchronized块是红色鲱鱼。您的问题是,您有N个线程,并且您有两个代码块,并且您希望确保没有任何线程进入第二个块,直到所有线程完成第一个块。

你使用CyclicBarrierhttp://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html

答案 3 :(得分:-2)

您应该可以在致电block1之前使用block2,并在致电static Lock lock = new ReentrantLock(); Random random = new Random(); public void block1() throws InterruptedException { System.out.println("Enter block 1"); Thread.sleep(random.nextInt(500)); System.out.println("Leave block 1"); } public void block2() throws InterruptedException { System.out.println("Enter block 2"); Thread.sleep(random.nextInt(500)); System.out.println("Leave block 2"); } private class BlockTester implements Runnable { long start = System.currentTimeMillis(); @Override public void run() { while (System.currentTimeMillis() < start + 10000) { lock.lock(); try { System.out.println("Thread: " + Thread.currentThread().getName()); block1(); block2(); } catch (InterruptedException ex) { System.out.println("Interrupted"); } finally { lock.unlock(); } } } } public void test() throws InterruptedException { Thread[] blockTesters = { new Thread(new BlockTester()), new Thread(new BlockTester()), new Thread(new BlockTester()), new Thread(new BlockTester()), new Thread(new BlockTester()) }; for (Thread t : blockTesters) { t.start(); } for (Thread t : blockTesters) { t.join(); } } 后发布。

AcmeAppBundle:Import:mapping.html.twig