美文网首页
Java技术学习:如何保证同一资源被多个线程并发访问时的完整性?

Java技术学习:如何保证同一资源被多个线程并发访问时的完整性?

作者: QFdongdong | 来源:发表于2019-02-22 17:57 被阅读0次

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

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

- 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<Object> list = new LinkedList<Object>();

    // 生产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<Object> getList() {

          return list;

    }

    public void setList(LinkedList<Object> list) {

          this.list = list;

    }

    public int getMAX_SIZE() {

          return MAX_SIZE;

    }

}

```

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

```

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

    // 仓库最大存储量

    private final int MAX_SIZE = 100;

    // 仓库存储的载体

    private LinkedList<Object> list = new LinkedList<Object>();

    // 锁

    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<Object> getList() {

          return list;

    }

    public void setList(LinkedList<Object> list) {

          this.list = list;

    }

}

相关文章

  • Java技术学习:如何保证同一资源被多个线程并发访问时的完整性?

    常用的同步方法是采用信号或加锁机制,保证资源在任意时刻至多被一个线程访问。Java语言在多线程编程上实现了完全对象...

  • Synchronized 关键字

    Java多线程中的同步机制会对资源进行加锁,保证同一时刻只有一个线程操作该资源,避免多个线程同时访问该资源造成冲突...

  • iOS中有哪些技术可以保证线程安全?

    iOS中有哪些技术可以保证线程安全? 1块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源,比如多个线...

  • 线程同步

    并发是同一个对象被多个线程同时操作。线程同步发生在多个线程操作同1个资源。线程同步需要有队列和锁同时保证.保证线程...

  • java并发学习

    java 高并发 基本概念 并发: 多个线程操作相同的资源,保证线程安全,合理使用资源 高并发: 服务能同时处理很...

  • iOS面试题总结(2018)

    1.说下线程和进程的区别 2.如何保证线程安全 一块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源,...

  • iOS面试题总结

    1.说下线程和进程的区别 2.如何保证线程安全 一块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源,...

  • 多线程(二)线程同步

    一、线程同步 一块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源。当多个线程访问同一块资源时,很容易...

  • 70-MySQL-事务-表级锁

    事务的隔离性是由锁来保证的 一、概述 锁是计算机协调多个进程或线程并发访问某一资源的机制。当多个线程并发访问某个数...

  • 信号量-semaphore -05

    并发中多个线程访问同一个资源可以通过同步解决,但是多个线程访问多个资源怎么解决呢?如公交车上有10个位置,但是现在...

网友评论

      本文标题:Java技术学习:如何保证同一资源被多个线程并发访问时的完整性?

      本文链接:https://www.haomeiwen.com/subject/actyyqtx.html