同一资源多线程并发访问时的完整性

简介:   同一资源多线程并发访问时的完整性,常用的同步方法是采用信号或加锁机制,确保资源在任意时刻至多被一个线程访问。Java语言在多线程编程上实现了完全对象化,提供了对同步机制的良好支持。  在Java中一共有四种方法支持同步,其中前三个是同步方法,一个是管道方法。

  同一资源多线程并发访问时的完整性,常用的同步方法是采用信号或加锁机制,确保资源在任意时刻至多被一个线程访问。Java语言在多线程编程上实现了完全对象化,提供了对同步机制的良好支持。

  在Java中一共有四种方法支持同步,其中前三个是同步方法,一个是管道方法。管道方法不建议使用,阻塞队列方法在问题4已有描述,现只提供前两种实现方法。

  - wait()/notify()方法

  - await()/signal()方法

  - BlockingQueue阻塞队列方法

  - PipedInputStream/PipedOutputStream

  一、生产者类:

  `

  public class Producer extends Thread { // 每次生产的产品数量

  private int num;

  // 所在放置的仓库

  private Storage storage;

  // 构造函数,设置仓库

  public Producer(Storage storage) {

  this.storage = storage;

  }

  // 线程run函数

  public void run() {

  produce(num);

  }

  // 调用仓库Storage的生产函数

  public void produce(int num) {

  storage.produce(num);

  }

  public int getNum() {

  return num;

  }

  public void setNum(int num) {

  this.num = num;

  }

  public Storage getStorage() {

  return storage;

  }

  public void setStorage(Storage storage) {

  this.storage = storage;

  }

  }

  `

  二、消费者类:

  `

  public class Consumer extends Thread { // 每次消费的产品数量

  private int num;

  // 所在放置的仓库

  private Storage storage;

  // 构造函数,设置仓库

  public Consumer(Storage storage) {

  this.storage = storage;

  }

  // 线程run函数

  public void run() {

  consume(num);

  }

  // 调用仓库Storage的生产函数

  public void consume(int num) {

  storage.consume(num);

  }

  // get/set方法

  public int getNum() {

  return num;

  }

  public void setNum(int num) {

  this.num = num;

  }

  public Storage getStorage() {

  return storage;

  }

  public void setStorage(Storage storage) {

  this.storage = storage;

  }

  }

  `

  仓库类:(wait()/notify()方法)

  `

  public class Storage { // 仓库最大存储量

  private final int MAX_SIZE = 100;

  // 仓库存储的载体

  private LinkedList list = new LinkedList();

  // 生产num个产品

  public void produce(int num) {

  // 同步代码段

  synchronized (list) {

  // 如果仓库剩余容量不足

  while (list.size() + num > MAX_SIZE) {

  System.out.print("【要生产的产品数量】:" + num);

  System.out.println(" 【库存量】:" + list.size() + " 暂时不能执行生产任务!");

  try {

  list.wait();// 由于条件不满足,生产阻塞

  } catch (InterruptedException e) {

  e.printStackTrace();

  }

  }

  // 生产条件满足情况下,生产num个产品

  for (int i = 1; i <= num; ++i) {

  list.add(new Object());

  }

  System.out.print("【已经生产产品数】:" + num);

  System.out.println(" 【现仓储量为】:" + list.size());

  list.notifyAll();

  }

  }

  // 消费num个产品

  public void consume(int num) {

  // 同步代码段

  synchronized (list) {

  // 如果仓库存储量不足

  while (list.size() < num) {

  System.out.print("【要消费的产品数量】:" + num);

  System.out.println(" 【库存量】:" + list.size() + " 暂时不能执行生产任务!");

  try {

  // 由于条件不满足,消费阻塞

  list.wait();

  } catch (InterruptedException e) {

  e.printStackTrace();

  }

  }

  // 消费条件满足情况下,消费num个产品

  for (int i = 1; i <= num; ++i) {

  list.remove();

  }

  System.out.print("【已经消费产品数】:" + num);

  System.out.println(" 【现仓储)量为】:" + list.size());

  list.notifyAll();

  }

  }

  // get/set方法

  public LinkedList getList() {

  return list;

  }

  public void setList(LinkedList list) {

  this.list = list;

  }

  public int getMAX_SIZE() {

  return MAX_SIZE;

  }

  }

  `

  仓库类:(await()/signal()方法)

  `

  public class Storage { // 仓库最大存储量

  // 仓库最大存储量

  private final int MAX_SIZE = 100;

  // 仓库存储的载体

  private LinkedList list = new LinkedList();

  // 锁

  private final Lock lock = new ReentrantLock();

  // 仓库满的条件变量

  private final Condition full = lock.newCondition();

  // 仓库空的条件变量

  private final Condition empty = lock.newCondition();

  // 生产num个产品

  public void produce(int num) {

  // 获得锁

  lock.lock();

  // 如果仓库剩余容量不足

  while (list.size() + num > MAX_SIZE) {

  System.out.print("【要生产的产品数量】:" + num);

  System.out.println(" 【库存量】:" + list.size() + " 暂时不能执行生产任务!");

  try {

  // 由于条件不满足,生产阻塞

  full.await();

  } catch (InterruptedException e) {

  e.printStackTrace();

  }

  }

  // 生产条件满足情况下,生产num个产品

  for (int i = 1; i <= num; ++i) {

  list.add(new Object());

  }

  System.out.print("【已经生产产品数】:" + num);

  System.out.println(" 【现仓储量为】:" + list.size());

  // 唤醒其他所有线程

  full.signalAll();

  empty.signalAll();

  // 释放锁

  lock.unlock();

  }

  // 消费num个产品

  public void consume(int num) {

  // 获得锁

  lock.lock();

  // 如果仓库存储量不足

  while (list.size() < num) {

  System.out.print("【要消费的产品数量】:" + num);

  System.out.println(" 【库存量】:" + list.size() + " 暂时不能执行生产任务!");

  try {

  // 由于条件不满足,消费阻塞

  empty.await();

  } catch (InterruptedException e) {

  e.printStackTrace();

  }

  }

  // 消费条件满足情况下,消费num个产品

  for (int i = 1; i <= num; ++i) {

  list.remove();

  }

  System.out.print("【已经消费产品数】:" + num);

  System.out.println(" 【现仓储)量为】:" + list.size());

  // 唤醒其他所有线程

  full.signalAll();

  empty.signalAll();

  // 释放锁

  lock.unlock();

  }

  // set/get方法

  public int getMAX_SIZE() {

  return MAX_SIZE;

  }

  public LinkedList getList() {

  return list;

  }

  public void setList(LinkedList list) {

  this.list = list;

  }

  }

相关文章
|
5天前
|
安全 Java
java线程之List集合并发安全问题及解决方案
java线程之List集合并发安全问题及解决方案
11 1
|
9天前
|
Java
Java Socket编程与多线程:提升客户端-服务器通信的并发性能
【6月更文挑战第21天】Java网络编程中,Socket结合多线程提升并发性能,服务器对每个客户端连接启动新线程处理,如示例所示,实现每个客户端的独立操作。多线程利用多核处理器能力,避免串行等待,提升响应速度。防止死锁需减少共享资源,统一锁定顺序,使用超时和重试策略。使用synchronized、ReentrantLock等维持数据一致性。多线程带来性能提升的同时,也伴随复杂性和挑战。
|
18天前
|
安全 Java API
Java并发基础-启动和终止线程
Java并发基础-启动和终止线程
23 0
|
3天前
|
Java 调度
Java多线程编程与并发控制策略
Java多线程编程与并发控制策略
|
3天前
|
安全 Java 开发者
Java并发编程:理解并发与多线程
在当今软件开发领域,Java作为一种广泛应用的编程语言,其并发编程能力显得尤为重要。本文将深入探讨Java中的并发编程概念,包括多线程基础、线程安全、并发工具类等内容,帮助开发者更好地理解和应用Java中的并发特性。
6 1
|
7天前
|
Java
Java中的`synchronized`关键字是一个用于并发控制的关键字,它提供了一种简单的加锁机制来确保多线程环境下的数据一致性。
【6月更文挑战第24天】Java的`synchronized`关键字确保多线程数据一致性,通过锁定代码块或方法防止并发冲突。同步方法整个方法体为临界区,同步代码块则锁定特定对象。示例展示了如何在`Counter`类中使用`synchronized`保证原子操作和可见性,同时指出过度使用可能影响性能。
19 4
|
11天前
|
监控 程序员 调度
协程实现单线程并发(入门)
协程实现单线程并发(入门)
15 1
|
3天前
|
NoSQL Redis
Redis系列学习文章分享---第五篇(Redis实战篇--优惠券秒杀,全局唯一id 添加优惠券 实现秒杀下单 库存超卖问题分析 乐观锁解决超卖 实现一人一单功能 集群下的线程并发安全问题)
Redis系列学习文章分享---第五篇(Redis实战篇--优惠券秒杀,全局唯一id 添加优惠券 实现秒杀下单 库存超卖问题分析 乐观锁解决超卖 实现一人一单功能 集群下的线程并发安全问题)
6 0
|
4天前
|
缓存 并行计算 安全
【并发编程系列一】并发编年史:线程的双刃剑——从优势到风险的全面解析
【并发编程系列一】并发编年史:线程的双刃剑——从优势到风险的全面解析
|
7天前
|
Java
synchronized关键字在Java中为多线程编程提供了一种简便的方式来管理并发,防止数据竞争和死锁等问题
Java的`synchronized`关键字确保多线程环境中的数据一致性,通过锁定代码段或方法防止并发冲突。它可修饰方法(整个方法为临界区)或代码块(指定对象锁)。例如,同步方法只允许一个线程执行,同步代码块则更灵活,可锁定特定对象。使用时需谨慎,以避免性能影响和死锁。
10 0