Java并发编程多线程间的同步控制和通信详解
背景介绍
在多线程并发编程中,控制多个线程的同步和通信是非常重要的话题。如果多个线程之间没有良好的同步控制和通信机制,就会导致数据竞争、死锁、饥饿等问题,从而降低程序的性能和可靠性。因此,在Java并发编程中,多线程间的同步控制和通信是一项非常重要的技能。
同步控制
什么是同步控制?
同步控制是一种机制,用于确保多个线程之间可以协调工作,防止数据竞争和不确定性问题。Java中使用synchronized关键字和Lock对象提供同步控制。
synchronized关键字的使用方法
synchronized关键字是Java中提供最常用的同步控制机制。它可以用于修饰方法和代码块,并且只有一个线程可以访问被synchronized关键字修饰的代码。示例代码如下:
public class SynchronizedExample {
private int count = 0;
public synchronized void increment() {
count++;
}
}
在上面的代码中,increment方法被synchronized关键字修饰,表示该方法是一个同步方法,只有一个线程可以同时执行该方法。
Lock对象的使用方法
Lock对象是Java中提供的另一种同步控制机制。相比synchronized关键字,Lock对象提供了更加细粒度的控制和更高的性能。示例代码如下:
public class LockExample {
private Lock lock = new ReentrantLock();
private int count = 0;
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
}
在上面的代码中,increment方法使用了Lock对象进行同步控制。通过lock.lock()方法获取锁对象,并在finally语句块中使用lock.unlock()方法释放锁对象。
通信机制
什么是通信机制?
通信机制是指多个线程之间可以协调工作,进行数据交换和同步操作的机制。Java中使用wait(), notify()和notifyAll()方法提供通信机制。
wait()和notify()的使用方法
wait()和notify()方法是Object类中提供的方法,可以用于在多个线程之间进行等待和唤醒的操作。示例代码如下:
public class WaitNotifyExample {
private Object lock = new Object();
private int count = 0;
public void increment() throws InterruptedException {
synchronized (lock) {
while (count == 5) {
lock.wait();
}
count++;
System.out.println("Thread " + Thread.currentThread().getId() + " incremented count to " + count);
lock.notify();
}
}
public void decrement() throws InterruptedException {
synchronized (lock) {
while (count == 0) {
lock.wait();
}
count--;
System.out.println("Thread " + Thread.currentThread().getId() + " decremented count to " + count);
lock.notify();
}
}
}
在上面的代码中,increment()和decrement()方法使用了wait()和notify()方法进行通信操作。当count等于5时,increment()方法会调用lock.wait()方法进行等待,直到其他线程通过lock.notify()方法唤醒它。当count等于0时,decrement()方法也会调用lock.wait()方法进行等待,直到其他线程通过lock.notify()方法唤醒它。
notifyAll()的使用方法
notifyAll()方法是Object类中提供的另一种唤醒等待线程的方法。与notify()方法不同,notifyAll()方法会唤醒所有正在等待的线程。示例代码如下:
public class NotifyAllExample {
private Object lock = new Object();
private int count = 0;
public void increment() throws InterruptedException {
synchronized (lock) {
while (count == 5) {
lock.wait();
}
count++;
System.out.println("Thread " + Thread.currentThread().getId() + " incremented count to " + count);
lock.notifyAll();
}
}
public void decrement() throws InterruptedException {
synchronized (lock) {
while (count == 0) {
lock.wait();
}
count--;
System.out.println("Thread " + Thread.currentThread().getId() + " decremented count to " + count);
lock.notifyAll();
}
}
}
在上面的代码中,increment()和decrement()方法使用了notifyAll()方法进行通信操作。如果有多个线程等待进入synchronized代码块,notifyAll()方法会唤醒所有等待线程,而不是唤醒其中一个线程。
示例说明
示例1:使用synchronized关键字进行同步控制
下面的示例代码演示了如何使用synchronized关键字进行同步控制:
public class SynchronizedExample {
private int count = 0;
public synchronized void increment() {
count++;
}
public void run() {
for (int i = 0; i < 100000; i++) {
increment();
}
}
public static void main(String[] args) throws InterruptedException {
SynchronizedExample se = new SynchronizedExample();
Thread t1 = new Thread(se::run);
Thread t2 = new Thread(se::run);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Count: " + se.count);
}
}
在上面的代码中,SynchronizedExample类中的increment()方法被synchronized关键字修饰,表示该方法是一个同步方法。在main()方法中,创建了两个线程t1和t2,并分别调用了SynchronizedExample类中的run()方法。通过运行该程序,输出的结果应该为:Count: 200000
示例2:使用wait()和notify()方法进行线程通信
下面的示例代码演示了如何使用wait()和notify()方法进行线程间的通信:
public class WaitNotifyExample {
private Object lock = new Object();
private int count = 0;
public void increment() throws InterruptedException {
synchronized (lock) {
while (count == 5) {
lock.wait();
}
count++;
System.out.println("Thread " + Thread.currentThread().getId() + " incremented count to " + count);
lock.notify();
}
}
public void decrement() throws InterruptedException {
synchronized (lock) {
while (count == 0) {
lock.wait();
}
count--;
System.out.println("Thread " + Thread.currentThread().getId() + " decremented count to " + count);
lock.notify();
}
}
public static void main(String[] args) throws InterruptedException {
WaitNotifyExample wne = new WaitNotifyExample();
Runnable r1 = () -> {
try {
for (int i = 0; i < 10; i++) {
wne.increment();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
};
Runnable r2 = () -> {
try {
for (int i = 0; i < 10; i++) {
wne.decrement();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
};
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
t1.join();
t2.join();
}
}
在上面的代码中,WaitNotifyExample类使用了wait()和notify()方法进行线程间的通信操作。在main()方法中,创建了两个线程t1和t2,分别调用了WaitNotifyExample类中的increment()和decrement()方法。其中,increment()方法会对count进行自增操作;decrement()方法会对count进行自减操作。当count等于5时,increment()方法会调用lock.wait()方法进行等待;当count等于0时,decrement()方法也会调用lock.wait()方法进行等待。在每次increment()或decrement()方法结束时,调用lock.notify()方法唤醒其他等待线程。
通过运行该程序,可以观察到线程之间的通信机制,输出结果应该类似于下面的内容:
Thread 10 incremented count to 1
Thread 11 incremented count to 2
Thread 10 incremented count to 3
Thread 11 incremented count to 4
Thread 10 incremented count to 5
Thread 11 decremented count to 4
Thread 10 decremented count to 3
Thread 11 decremented count to 2
Thread 10 decremented count to 1
Thread 11 decremented count to 0
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java并发编程多线程间的同步控制和通信详解 - Python技术站