public class Main {
public static void main(String[] agrs) {
T1 t1 = new T1();
T2 t2 = new T2();
t1.start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.start();
}
public static Integer lockObj = new Integer(0);
}class T1 extends Thread {
public void run() {
synchronized(Main.lockObj) {
for (int i= 65; i< 70; ++i) {
System.out.print(String.format("%d = ", i));
try {
Main.lockObj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}class T2 extends Thread {
public void run() {
for (char i= 'A'; i< 'F'; ++i) {
synchronized(Main.lockObj) {
System.out.println(i);
Main.lockObj.notify();
}
try {
sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
上面的代码就是两个线程,如果T2不sleep的话,就不能交替执行。程序本意是T1打印一行,然后wait释放锁,T2就能获得锁,T2获得锁之后打印一行,然后notify把锁还给T1,这就出问题了,T2调notify之后并不是正在wait的T1的重新获得,因为此时T2也想获得锁,有可能又被T2获得了。所以,顺序就乱了,如果在T2里面加个延时,就对了,T2在notify之后,延时100毫秒,才能保证被T1抢过来。
class T1 extends Thread {
public void run() {
for (int i= 65; i< 70; ++i) {
synchronized(Main.lockObj) {
System.out.print(String.format("%d = ", i));
}
Thread.yield();
}
}
}class T2 extends Thread {
public void run() {
for (char i= 'A'; i< 'F'; ++i) {
synchronized(Main.lockObj) {
System.out.println(i);
}
Thread.yield();
}
}
}由于yield()不释放锁,所以要放在synchronized外面
对的!这个说法是准确的。notify只是唤醒了一个因为调用了wait而自愿阻塞的线程,它现在可以执行了,但是,能不能访问,要看该对该对象加锁的线程是否已经释放了锁(两种方式:第一该线程运行同步方法已经结束,第二该线程调用了wait方法,自愿阻塞)。
synchronized(obj) WaitForSingleObject(obj)
{ ..
obj.wait(); Release...()
WaitForSingleObject(obj)
} Release...()也就是说,wait应该是释放之后再重新获得,也就是分两步来的,那最后谁获得锁都不一定了
具体是那个没有保障你的需求其实可以这样思想,不需要睡眠 public static void test2() { T3 t3 = new T3();
T4 t4 = new T4();
t3.start();
t4.start();
}
public static Integer lockObj = new Integer(0);
}class T3 extends Thread {
public void run() {
try {
synchronized (Main.lockObj) {
for (int i = 65; i < 70; ++i) {
System.out.print(String.format("%d = ", i));
Main.lockObj.notify();
Main.lockObj.wait();
}
Main.lockObj.notify();//这一句很重要,不然T4的wait将没有人来唤醒
//程序会无法结束,这也表现了,在线程中切来换去
//是很危险的极易造成死锁,小心+小心
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}class T4 extends Thread {
public void run() {
try{
synchronized(Main.lockObj) {
for (char i= 'A'; i< 'F'; ++i) {
System.out.println(i);
Main.lockObj.notify();
Main.lockObj.wait();
}
}
}catch(InterruptedException e){
e.printStackTrace();
}
}
}