Conditional Variable

本博客转自:https://originals-tz.github.io/

0x00 什么是Conditional Variable

通常,线程进入临界区,却发现在某一条件满足后它才能执行

要使用一个条件对象管理那些已经获得了锁但是却不能做有用工作的进程

也就是说,如果条件不满足,则等待。当条件满足时,等待该条件的线程将被唤醒

举个简单的例子,handle_file线程要处理文件,download_file线程要下载文件

但是要先下载后才能打开,所以,handle_file即使获得了锁,也要等待download_file把文件下载完

这时候就需要条件变量

0x01 取款和存款问题

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
* Java线程:条件变量
*
* @author leizhimin 2009-11-5 10:57:29
*/
public class Test {
        public static void main(String[] args) {
                //创建并发访问的账户
                MyCount myCount = new MyCount("95599200901215522", 10000);
                //创建一个线程池
                ExecutorService pool = Executors.newFixedThreadPool(2);
                Thread t1 = new SaveThread("张三", myCount, 2000);
                Thread t2 = new SaveThread("李四", myCount, 3600);
                Thread t3 = new DrawThread("王五", myCount, 2700);
                Thread t4 = new SaveThread("老张", myCount, 600);
                Thread t5 = new DrawThread("老牛", myCount, 1300);
                Thread t6 = new DrawThread("胖子", myCount, 800);
                //执行各个线程
                pool.execute(t1);
                pool.execute(t2);
                pool.execute(t3);
                pool.execute(t4);
                pool.execute(t5);
                pool.execute(t6);
                //关闭线程池
                pool.shutdown();
        }
}

/**
* 存款线程类
*/
class SaveThread extends Thread {
        private String name;                //操作人
        private MyCount myCount;        //账户
        private int x;                            //存款金额

        SaveThread(String name, MyCount myCount, int x) {
                this.name = name;
                this.myCount = myCount;
                this.x = x;
        }

        public void run() {
                myCount.saving(x, name);
        }
}

/**
* 取款线程类
*/
class DrawThread extends Thread {
        private String name;                //操作人
        private MyCount myCount;        //账户
        private int x;                            //存款金额

        DrawThread(String name, MyCount myCount, int x) {
                this.name = name;
                this.myCount = myCount;
                this.x = x;
        }

        public void run() {
                myCount.drawing(x, name);
        }
}


/**
* 普通银行账户,不可透支
*/
class MyCount {
        private String oid;                         //账号
        private int cash;                             //账户余额
        private Lock lock = new ReentrantLock();                //账户锁
        private Condition _save = lock.newCondition();    //存款条件
        private Condition _draw = lock.newCondition();    //取款条件

        MyCount(String oid, int cash) {
                this.oid = oid;
                this.cash = cash;
        }

        /**
         * 存款
         *
         * @param x        操作金额
         * @param name 操作人
         */
        public void saving(int x, String name) {
                lock.lock();                        //获取锁
                if (x > 0) {
                        cash += x;                    //存款
                        System.out.println(name + "存款" + x + ",当前余额为" + cash);
                }
                _draw.signalAll();            //唤醒所有等待线程。
                lock.unlock();                    //释放锁
        }

        /**
         * 取款
         *
         * @param x        操作金额
         * @param name 操作人
         */
        public void drawing(int x, String name) {
                lock.lock();                                 //获取锁
                try {
                        if (cash - x < 0) {
                                _draw.await();             //阻塞取款操作
                        } else {
                                cash -= x;                     //取款
                                System.out.println(name + "取款" + x + ",当前余额为" + cash);
                        }
                        _save.signalAll();             //唤醒所有存款操作
                } catch (InterruptedException e) {
                        e.printStackTrace();
                } finally {
                        lock.unlock();                     //释放锁
                }
        }
}

MyCount里面有取款和存款的方法,设置多个线程分别执行这两个方法

当一个取款线程获取了锁,但是发现钱不够了,然后就会进入等待队列,等待存款的进程将其唤醒

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值