当前位置:实例文章 » 其他实例» [文章]【Java基础教程】(四十三)多线程篇 · 下:深入剖析Java多线程编程:同步、死锁及经典案例——生产者与消费者,探究sleep()与wait()的差异

【Java基础教程】(四十三)多线程篇 · 下:深入剖析Java多线程编程:同步、死锁及经典案例——生产者与消费者,探究sleep()与wait()的差异

发布人:shili8 发布时间:2025-02-13 21:40 阅读次数:0

**Java基础教程**(四十三) 多线程篇 · 下**深入剖析Java多线程编程:同步、死锁及经典案例——生产者与消费者**

在前面的文章中,我们已经学习了Java中的基本线程概念和相关方法。然而,实际开发中,往往需要处理复杂的线程逻辑,这就涉及到了同步和死锁的问题。在本文中,我们将深入剖析这些问题,并通过经典案例——生产者与消费者来进行演示。

###1. 同步在多线程环境下,共享资源可能会被多个线程同时访问,这就需要一种机制来保证数据的一致性。这种机制就是同步。

####1.1 synchronized关键字Java提供了`synchronized`关键字来实现同步。这个关键字可以应用于方法、类或块上,用于锁定资源以防止多线程同时访问。

javapublic class SynchronizedExample {
 private int count =0;

 public void increment() {
 synchronized (this) { // 锁定当前对象 count++;
 }
 }

 public int getCount() {
 synchronized (this) { // 锁定当前对象 return count;
 }
 }
}


在上面的例子中,`increment()`和`getCount()`方法都使用了`synchronized`关键字来锁定资源。这样就保证了数据的一致性。

####1.2 ReentrantLock除了`synchronized`关键字之外,Java还提供了`ReentrantLock`类来实现同步。这个类比`synchronized`更灵活和高效。

javaimport java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockExample {
 private int count =0;
 private final ReentrantLock lock = new ReentrantLock();

 public void increment() {
 lock.lock(); // 锁定资源 try {
 count++;
 } finally {
 lock.unlock(); // 解锁资源 }
 }

 public int getCount() {
 lock.lock(); // 锁定资源 try {
 return count;
 } finally {
 lock.unlock(); // 解锁资源 }
 }
}


在上面的例子中,`increment()`和`getCount()`方法都使用了`ReentrantLock`类来实现同步。

###2. 死锁死锁是指两个或多个线程在竞争共享资源时,造成了循环等待现象,从而导致所有线程都无法继续执行下去。

####2.1 死锁的条件要发生死锁,必须满足以下四个条件:

* **互斥性**: 多个线程同时访问同一资源。
* **占有和等待**: 线程占有一个资源,同时等待另一个资源。
* **不剥夺**: 线程占有资源后,不会被其他线程剥夺。
* **循环等待**: 多个线程之间形成了循环等待现象。

####2.2 死锁的避免要避免死锁,必须破坏上述四个条件之一。最简单的方法是使用`synchronized`关键字或`ReentrantLock`类来实现同步,这样就可以保证资源的一致性。

###3. 经典案例——生产者与消费者生产者与消费者是一个经典的多线程案例,涉及到生产者和消费者的交互逻辑。这个案例可以用来演示多线程编程中的同步和死锁问题。

####3.1 生产者与消费者类
javaimport java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ProducerConsumerExample {
 private final Lock lock = new ReentrantLock();
 private final Condition notFull = lock.newCondition();
 private final Condition notEmpty = lock.newCondition();
 private int count =0;
 private boolean isFull = false;

 public void produce() {
 lock.lock(); // 锁定资源 try {
 while (isFull) { // 等待缓冲区不满 notFull.await(); // 等待缓冲区不满 }
 count++;
 isFull = true;
 System.out.println("生产者生产了一个产品,当前数量为:" + count);
 notEmpty.signal(); // 通知消费者 } catch (InterruptedException e) {
 Thread.currentThread().interrupt();
 } finally {
 lock.unlock(); // 解锁资源 }
 }

 public void consume() {
 lock.lock(); // 锁定资源 try {
 while (!isFull) { // 等待缓冲区满了 notEmpty.await(); // 等待缓冲区满了 }
 count--;
 isFull = false;
 System.out.println("消费者消费了一个产品,当前数量为:" + count);
 notFull.signal(); // 通知生产者 } catch (InterruptedException e) {
 Thread.currentThread().interrupt();
 } finally {
 lock.unlock(); // 解锁资源 }
 }
}


在上面的例子中,`produce()`和`consume()`方法都使用了`synchronized`关键字来实现同步。这个案例演示了生产者与消费者的交互逻辑,以及如何避免死锁。

###4. sleep()与wait()

`sleep()`和`wait()`都是用于暂停线程执行的方法,但是它们有不同的作用和使用场景。

####4.1 sleep()

`sleep()`方法是用来暂停当前线程的执行时间,直到指定的毫秒数。这个方法可以用来实现睡眠效果。

javapublic class SleepExample {
 public void sleep() {
 try {
 Thread.sleep(1000); // 暂停1秒 } catch (InterruptedException e) {
 Thread.currentThread().interrupt();
 }
 }
}


在上面的例子中,`sleep()`方法使用了`Thread.sleep()`方法来暂停线程的执行时间。

####4.2 wait()

`wait()`方法是用来暂停当前线程的执行,并等待其他线程通知。这个方法可以用来实现等待效果。

javapublic class WaitExample {
 private final Lock lock = new ReentrantLock();
 private boolean isReady = false;

 public void wait() {
 lock.lock(); // 锁定资源 try {
 while (!isReady) { // 等待准备好 lock.wait(); // 等待准备好 }
 System.out.println("准备好了");
 } catch (InterruptedException e) {
 Thread.currentThread().interrupt();
 } finally {
 lock.unlock(); // 解锁资源 }
 }

 public void notify() {
 lock.lock(); // 锁定资源 try {
 isReady = true;
 lock.notifyAll(); // 通知等待线程 } finally {
 lock.unlock(); // 解锁资源 }
 }
}


在上面的例子中,`wait()`和`notify()`方法都使用了`synchronized`关键字来实现同步。这个案例演示了如何使用`wait()`和`notify()`方法来实现等待效果。

###5. 总结本文深入剖析了Java多线程编程中的同步、死锁及经典案例——生产者与消费者。通过上述内容,我们可以看出,多线程编程中需要考虑到资源的共享和互斥性,以及如何避免死锁的问题。同时,我们也学习到了如何使用`synchronized`关键字和`ReentrantLock`类来实现同步,以及如何使用`sleep()`和`wait()`方法来暂停线程的执行。

###6. 参考* [Java多线程编程]( />* [Java并发API]( />* [生产者与消费者问题](

相关标签:java多线程基础
其他信息

其他资源

Top