synchronized 代码块与 wait和notify方法密不可分 <#
2023-09-07 23:19:52
<#title>synchronized 代码块与 wait和notify方法密不可分 <#/title>
在Java多线程编程中,synchronized代码块和wait/notify方法是两个重要的同步机制,它们可以使多个线程安全地访问共享资源。
<#title>synchronized代码块<#/title>
synchronized代码块是Java语言中的一个同步机制,它允许你在一个多线程环境中保护共享资源,使线程能够顺序地访问这些资源。使用synchronized代码块时,只需要在需要保护的代码块前面加上synchronized,然后在括号内指定要保护的资源。例如:
public class SharedResource {
private int value;
public synchronized void increment() {
value++;
}
}
这段代码中,increment方法被synchronized关键字修饰,这意味着每次只有一个线程可以执行这个方法。这样就可以防止多个线程同时访问value变量,从而保证了value变量的原子性。
<#title>wait和notify方法<#/title>
wait和notify方法是Java语言中的两个线程通信机制,它们允许线程在等待其他线程完成某项任务后继续执行。wait方法使当前线程进入休眠状态,直到另一个线程调用了notify或notifyAll方法之后,才能继续恢复执行。notify方法唤醒一个在该对象上等待的线程,而notifyAll方法唤醒所有在该对象上等待的线程。
public class WaitNotifyExample {
private Object lock = new Object();
private boolean flag = false;
public void producer() {
synchronized (lock) {
while (flag) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
flag = true;
lock.notify();
}
}
public void consumer() {
synchronized (lock) {
while (!flag) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
flag = false;
lock.notify();
}
}
}
这段代码中,producer方法和consumer方法都使用synchronized关键字修饰,这意味着每次只有一个线程可以执行这些方法。producer方法使用wait方法使当前线程进入休眠状态,直到consumer方法调用了notify方法之后,才能继续恢复执行。consumer方法使用wait方法使当前线程进入休眠状态,直到producer方法调用了notify方法之后,才能继续恢复执行。这样就可以保证producer方法和consumer方法交替执行,从而实现线程之间的通信。
<#title>为什么wait和notify必须放在synchronized代码块中<#/title>
因为wait和notify方法只能在拥有锁的情况下才能被调用,而synchronized代码块可以为代码提供一个临时的锁。当一个线程进入synchronized代码块时,它会获取锁,这样其他线程就无法进入这个代码块。当一个线程在synchronized代码块中调用wait方法时,它会释放锁,并进入休眠状态。当另一个线程调用notify或notifyAll方法时,被唤醒的线程会重新获取锁,并继续执行synchronized代码块。
如果wait和notify方法不在synchronized代码块中,那么就有可能出现多个线程同时调用wait或notify方法的情况,这会导致程序出现异常。例如:
public class UnsynchronizedWaitNotifyExample {
private boolean flag = false;
public void producer() {
while (flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
flag = true;
notify();
}
public void consumer() {
while (!flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
flag = false;
notify();
}
}
这段代码中,producer方法和consumer方法都不使用synchronized关键字修饰,这意味着多个线程可以同时执行这些方法。当producer方法和consumer方法同时调用wait方法时,就会出现异常。这是因为wait方法只能在拥有锁的情况下才能被调用,而这段代码中没有使用synchronized关键字,所以没有锁。
<#title>总结<#/title>
在Java多线程编程中,wait和notify方法只能在synchronized代码块或方法中才能正常使用。这是因为wait和notify方法只能在拥有锁的情况下才能被调用,而synchronized代码块可以为代码提供一个临时的锁。如果不使用synchronized代码块,那么就有可能出现多个线程同时调用wait或notify方法的情况,这会导致程序出现异常。