起因是一道笔试题:
http://edisonxu.org/2017/03/02/java-thread-communication.html#comments
(上面这篇文章中提到的关于volatile的答案似乎有问题)
几个坑的地方:
1. wait() 和notify() 一定是在synchronized()块中出现
wait() 发生时会当前线程释放锁
notify()发生时,会?
2. notify() 出现在wait() 之前则无效(和条件变量的区别)
3. Integer虽然可以调用wait(),notify(),但是由于赋新值时会改变对象,所以不能用在这里,要自己定义一个类似的东西
我的代码:
package mytest;
public class ThreadTest {
static class ThreadNum{
public int i;
public ThreadNum(int value){
i=value;
}
}
private Object w1=new Object ();
private Object w2=new Object();
private Object o=new Object();
private ThreadNum cur=new ThreadNum(1);//must use self-define type
public Runnable newThreadOne() {
return new Runnable() {
public void run() {
try {
for (int i = 0; i < 52; i=i+2) {
synchronized (cur) {//must inside synchronized block
if(cur.i==2)//从逻辑上来说,只有两个线程if应该没问题;但是有个叫Spurious wakeup 的东西要求这个地方一定要用while,然而懒得改了
{
cur.wait();
}
System.out.print(i+1);
System.out.print(i+2);
cur.i=2;
cur.notify();
}
}
} catch (InterruptedException e) {
System.out.println("Oops...");
}
}
};
}
public Runnable newThreadTwo() {
return new Runnable() {
public void run() {
try {
for (int i = 0; i < 26; i++) {
synchronized (cur) {
if(cur.i==1)
{
cur.wait();
}
System.out.print((char)('a'+i));
cur.i=1;
cur.notify();
}
}
} catch (InterruptedException e) {
System.out.println("Oops...");
}
}
};
}
public static void main(String args[]) throws InterruptedException {
/*
Object o=new Object();
synchronized (o) {
o.notify();
System.out.println("notified");
o.wait();
System.out.println("wait");
}*/
ThreadTest test = new ThreadTest();
Thread t1=new Thread(test.newThreadOne());
Thread t2=new Thread(test.newThreadTwo());
t1.start();
t2.start();
}
}
java的signal函数似乎一定是要持有锁的线程调用,这点和C的pthread_cond_t
不同
package mytest;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ConditionTest {
private Lock lock=new ReentrantLock(true);
private Condition condition1=lock.newCondition();
private Condition condition2=lock.newCondition();
private int thread_to_run=1;
public Runnable newThreadOne() {
return new Runnable() {
public void run() {
try {
for (int i = 0; i < 52; i=i+2) {
synchronized (lock) {
while(thread_to_run!=1){
condition1.wait();
}
System.out.print(i+1);
System.out.print(i+2);
condition2.signal();
}
}
} catch (InterruptedException e) {
System.out.println("Oops...");
}
}
};
}
public Runnable newThreadTwo() {
return new Runnable() {
public void run() {
try {
for (int i = 0; i < 26; i++) {
synchronized (lock) {
while(thread_to_run!=2){
condition2.await();
}
System.out.print((char)('a'+i));
condition1.signal();
}
}
} catch (InterruptedException e) {
System.out.println("Oops...");
}
}
};
}
public static void main(String args[]) throws InterruptedException {
/*
Lock lock=new ReentrantLock(true);
Condition condition1=lock.newCondition();
condition1.signal();
System.out.println("signal");
lock.lock();
System.out.println("before wait");
condition1.await();
System.out.println("wait");
condition1.signal();
System.out.println("signal");
lock.unlock();
*/
ThreadTest test = new ThreadTest();
Thread t1=new Thread(test.newThreadOne());
Thread t2=new Thread(test.newThreadTwo());
t1.start();
t2.start();
t1.join();
t2.join();
}
}
个人感觉信号量的版本最简单,因为这是一个关于顺序控制的问题,所以信号量会直接管理一个相关的计数器,不用像前面的程序那样需要自己控制另外一个变量
package mytest;
import java.util.concurrent.Semaphore;
public class SemaphoreTest {
static class ThreadNum{
public int i;
public ThreadNum(int value){
i=value;
}
}
private Semaphore w1=new Semaphore(1);
private Semaphore w2=new Semaphore(0);
public Runnable newThreadOne() {
return new Runnable() {
public void run() {
try {
for (int i = 0; i < 52; i=i+2) {
w1.acquire();
System.out.print(i+1);
System.out.print(i+2);
w2.release();
}
} catch (InterruptedException e) {
System.out.println("Oops...");
}
}
};
}
public Runnable newThreadTwo() {
return new Runnable() {
public void run() {
try {
for (int i = 0; i < 26; i++) {
w2.acquire();
System.out.print((char)('a'+i));
w1.release();
}
} catch (InterruptedException e) {
System.out.println("Oops...");
}
}
};
}
public static void main(String args[]) throws InterruptedException {
ThreadTest test = new ThreadTest();
Thread t1=new Thread(test.newThreadOne());
Thread t2=new Thread(test.newThreadTwo());
t1.start();
t2.start();
t1.join();
t2.join();
}
}
参考:
1.异常
http://blog.csdn.net/historyasamirror/article/details/6709693
2.条件变量
http://blog.csdn.net/woshixuye/article/details/28283289
3.