同步:线程以相同的顺序执行两个临界区
synchronization : Threads execute two critical sections in same order
我有以下类型的代码:
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
之前使用的 Lock
并在调用 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();
}
}
这基本上创建了一个队列,线程将在其中等待直到它们的数量出现。 [更新]
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 相同的顺序执行
If thread T1 executes block1 before thread T2, then T1 should execute block2 before T2. There are more than two threads.
那么可能会使用一个Queue来保证执行的顺序
private Object lock = new Object();
private Queue<Thread> threadQueue = new ArrayDeque<>();
//
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.
}
但是 如果一个线程 dies/exits 没有从队列中移除自己,那么后面的线程将被无限期地阻塞。也许添加一个 finally 块来做内务处理?
注意:在中建议使用头寸顺序而不是队列,这样似乎效率更高一些。
您示例中的 synchronized
块是一个转移注意力的问题。你的问题是,你有 N 个线程,你有两个代码块,你想确保 none 个线程进入第二个块,直到所有线程都完成第一个块。
你为此使用 CyclicBarrier
。 http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html
我有以下类型的代码:
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
之前使用的 Lock
并在调用 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();
}
}
这基本上创建了一个队列,线程将在其中等待直到它们的数量出现。 [更新]
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 相同的顺序执行
If thread T1 executes block1 before thread T2, then T1 should execute block2 before T2. There are more than two threads.
那么可能会使用一个Queue来保证执行的顺序
private Object lock = new Object();
private Queue<Thread> threadQueue = new ArrayDeque<>();
//
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.
}
但是 如果一个线程 dies/exits 没有从队列中移除自己,那么后面的线程将被无限期地阻塞。也许添加一个 finally 块来做内务处理?
注意:在
您示例中的 synchronized
块是一个转移注意力的问题。你的问题是,你有 N 个线程,你有两个代码块,你想确保 none 个线程进入第二个块,直到所有线程都完成第一个块。
你为此使用 CyclicBarrier
。 http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html