【发布时间】:2017-06-13 05:05:00
【问题描述】:
在使用 Semaphore 时我应该注意多线程问题吗? 经过我的测试似乎有一段时间 Semaphore#release 不会导致获取唤醒,即使有足够的许可。
底部是我的测试代码。
- 具有 2 个许可证的信号量
- 线程 3 和线程 2 先上
- thread-3 获得许可,等待
lock将由 thread-1 通知 - thread-2 获得许可,等待
lock1将由 thread-3 通知 - 线程 1 启动,休眠 30ms 线程 1 和线程 2 先启动
- thread-1 通知
lock,获取 2 个许可 - 线程 3 唤醒,通知
lock1,sleep(1)休眠 1 毫秒,线程 2 先获取许可,释放许可 - thread-2 唤醒,获取许可,然后释放许可并释放另一个许可
随机迭代会导致死锁,并输出一些这样的日志。
in 3, a = 2
in 2 ,a = 2
in in 2 lock 1, a = 0
in 1 , a = 0
acquire and release 3
in in 2 locked, a = 0
out 3 ,a = 0
in 1 locked, a = 0
acquire and release 2
out 2
out 1 ,a = 2
-------------------------------------------------------------- 0
in 2 ,a = 2
in 3, a = 1
in 1 , a = 0
in in 2 lock 1, a = 0
acquire and release 3
out 3 ,a = 1
//deadlock here
thread-3 Semaphore release permit后,thread-2不唤醒,thread-1和thread-3永远等待acquire
bleow 是我的测试代码
import java.util.concurrent.Semaphore;
/**
* Created by rqg on 6/10/17.
*/
public class WaitTest {
public static void main(String[] args) throws InterruptedException {
Semaphore semaphore = new Semaphore(2);
final Object lock = new Object();
final Object lock1 = new Object();
// testSemaphore(semaphore, lock, lock1);
for (int i = 0; i < 10000; i++) {
testSemaphore(semaphore, lock, lock1);
System.out.println("--------------------------------------------------------------------------------- " + i);
}
}
private static void testSemaphore(Semaphore semaphore, Object lock, Object lock1) throws InterruptedException {
Thread t1 = new Thread() {
@Override
public void run() {
try {
Thread.sleep(30);
synchronized (lock) {
lock.notify();
}
System.out.println("in 1 , a = " + semaphore.availablePermits());
semaphore.acquire(2);
System.out.println("in 1 locked, a = " + semaphore.availablePermits());
} catch (InterruptedException e) {
e.printStackTrace();
}
semaphore.release(2);
System.out.println("out 1 ,a = " + semaphore.availablePermits());
}
};
Thread t2 = new Thread() {
@Override
public void run() {
try {
System.out.println("in 2 ,a = " + semaphore.availablePermits());
semaphore.acquire();
synchronized (lock1) {
lock1.wait();
}
System.out.println("in in 2 lock 1, a = " + semaphore.availablePermits());
semaphore.acquire();
System.out.println("in in 2 locked, a = " + semaphore.availablePermits());
semaphore.release();
semaphore.release();
System.out.println("acquire and release 2");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("out 2");
}
};
Thread t3 = new Thread() {
@Override
public void run() {
try {
System.out.println("in 3, a = " + semaphore.availablePermits());
semaphore.acquire();
synchronized (lock) {
lock.wait();
}
synchronized (lock1) {
lock1.notify();
}
sleep(1);
semaphore.release();
System.out.println("acquire and release 3");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("out 3 ,a = " + semaphore.availablePermits());
}
};
t1.start();
t2.start();
t3.start();
t1.join();
t2.join();
t3.join();
}
}
这是我发生死锁时的胎面转储
【问题讨论】:
标签: java multithreading deadlock semaphore