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

Java 同步:线程以相同的顺序执行两个关键部分,java,multithreading,concurrency,semaphore,synchronisation,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

我有以下类型的代码:

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.
}
每个线程首先以相同的顺序执行块1、非同步块和块2

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


在java中有没有实现这一点的方法?

您应该能够在调用
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();
    }

}
staticlock=newreentrantlock();
随机=新随机();
public void block1()引发InterruptedException{
System.out.println(“输入块1”);
Thread.sleep(random.nextInt(500));
System.out.println(“离开区块1”);
}
public void block2()引发InterruptedException{
System.out.println(“输入块2”);
Thread.sleep(random.nextInt(500));
System.out.println(“离开区块2”);
}
私有类BlockTester实现可运行{
长启动=System.currentTimeMillis();
@凌驾
公开募捐{
而(System.currentTimeMillis()
这基本上创建了一个队列,线程将在队列中等待,直到其编号出现。[更新]

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();
 }

据我所知,关键部分#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.
    }
private Object lock=new Object();
私有队列threadQueue=new ArrayDeque();
// https://stackoverflow.com/questions/32353283/synchronization-threads-execute-two-critical-sections-in-same-order
public void executeCriticalSectionsInOrder()引发中断异常{
//临界截面#1
已同步(锁定){
//同步代码#1
//将self添加到队列
添加(Thread.currentThread());
}
//{许多不需要同步的代码}
//临界截面#2
已同步(锁定){
//在此线程之前执行block1的所有线程都应该已经执行了此块。
//轮候
Thread t=threadQueue.element();//只有在它是self时才能删除
while(t!=Thread.currentThread()){
lock.wait();
//睡觉后再试一次
t=threadQueue.element();
}
//已验证自己的回合。更新状态
threadQueue.remove();
//同步代码#2
lock.notifyAll();//退出节后唤醒所有等待的线程。
}
但是如果一个线程死亡/退出而未将自身从队列中移除,则后续线程将被不确定地阻止。是否可以添加一个finally块来执行内务管理


注意:在位置上,建议使用顺序而不是队列,这似乎更有效。

示例中的
已同步的
块是一个模糊的问题。您的问题是,您有N个线程,并且有两个代码块,并且您希望确保没有任何线程进入第二个块,直到他们中的所有人都完成了第一个街区


你可以使用
CyclicBarrier

我认为你不能在block1内调用
block2()
。@NicholasRobinson没有调用。所有代码都是按照给定的顺序执行的。这是在一个方法中吗?使用
synchronized(this){…}
还是它们是不同的方法?@NicholasRobinson所有东西都在一个方法中。{…}仅显示同步和非同步之间的分离blocks@NagarjunaSiddam线程数是否固定为2?您正在调用方法block1()和block2()一个接一个,我们不能把它们放在一个方法中吗?不知道这如何满足OP-他想要多个线程通过block1和其他不同步的代码-他不知道什么是一个线程超越另一个线程并首先到达Block2。具体地说,如果另一个线程之前通过block1,他想在Block2暂停一个线程它还没有消失。你是如何处理的:`{很多不需要同步的代码}`您正在锁定那些应该是同步块的类,但您也锁定了需要同步的编码器。@All-不是如果线程T1在线程T2之前执行block1,那么T1应该在T2之前执行block2,这意味着在
T1
完成
block2?只要检查一下,ThreadLocal定义可能必须是一个对象变量。我不明白为什么需要
ThreadLocal
——它的作用域是一个方法,而不是类。@而且我想你可以在方法中只输入一个int变量。应该会给出相同的结果。但是我评论说
ThreadLocal
可能需要是一个对象变量。+1表示对有趣概念的良好尝试(使用订单号而不是队列)。但是1)您选中的
place.get()
可能是指
position.get()
。2)不需要二次重叠锁。也可能是指
notNext.signalAll