锁对象

临界区:临界区是一个特殊的代码段,该代码段访问某种特殊的公共资源,该资源同一时间只允许一个线程使用。

Java中可以使用锁对象创造一个临界区:

 myLock.lock();
try {
关键代码
} finally {
myLock.unlock();
}

使用这种结构可以确保关键代码不会同时被多个线程执行,线程想要执行关键代码必须先获取“锁”,“锁”只能被一个线程持有,在该线程将“锁”释放前,其他线程因为获取不到锁而被阻塞,“锁”被释放的时候,之前因为获取这个锁被挂起的线程都会被唤醒,共同竞争着去获取锁。

将释放锁的操作写在finally里是很重要的,防止某个线程执行关键代码的时候因为抛出异常而没有将锁释放。

 package learnspringboot.xiao.learnjava.thread;

 import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; /**
* @author xzy
* @date 2019-12-13 11:01
* 说明:模拟银行转账
*/
public class Bank {
private Map<String, Double> accountMap = new HashMap<>();
private Lock myLock = new ReentrantLock();
private Condition haveMoney = myLock.newCondition(); public Bank() {
this.accountMap.put("ZhangSan", 100.0);
this.accountMap.put("WangWu", 1000.0);
} public void transfer(String from, String to, Double money) {
//线程执行后面的代码段需要先获得锁,获取不到就挂起。
myLock.lock();
System.out.println("当前获得锁的线程:" + Thread.currentThread().getName());
System.out.println(from + "想给" + to + "转" + money + "元," + from + "现在有" + accountMap.get(from) + "元");
try {
while (accountMap.get(from) < money) {
System.out.println("线程阻塞:" + Thread.currentThread().getName());
//获取到锁的线程需要等待本条件成立,条件成立前将锁释放,线程阻塞。
haveMoney.await();
}
accountMap.put(from, accountMap.get(from) - money);
accountMap.put(to, accountMap.get(to) + money);
System.out.println(from + "转给" + to + money + "元 线程:" + Thread.currentThread().getName());
//通知因本条件而挂起的线程,条件现在可能已经满足,可以试着再去获取肯看。
haveMoney.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
myLock.unlock();
}
} public static void main(String[] args) {
Bank bank = new Bank();
Thread thread1 = new Thread(() -> {
bank.transfer("ZhangSan", "WangWu", 500.0);
});
Thread thread2 = new Thread(() -> {
bank.transfer("WangWu", "ZhangSan", 1000.0);
});
Thread thread3 = new Thread(() -> {
bank.transfer("ZhangSan", "WangWu", 500.0);
});
thread1.setName("张三给王五500 x1");
thread2.setName("王五给张三1000");
thread3.setName("张三给王五500 x2");
thread1.start();
thread2.start();
thread3.start();
while (true) { }
}
}

Java锁对象和条件对象的使用的更多相关文章

  1. threading 官方 线程对象和锁对象以及条件对象condition

    官方地址:https://docs.python.org/2/library/threading.html#thread-objects 以下只截取condition部分,其他Lock()以及thre ...

  2. java 多线程(三)条件对象

    转载请注明出处:http://blog.csdn.net/xingjiarong/article/details/47417383 在上一篇博客中,我们学会了用ReentrantLock来控制线程訪问 ...

  3. Java锁机制了解一下

    前言 回顾前面: 多线程三分钟就可以入个门了! Thread源码剖析 多线程基础必要知识点!看了学习多线程事半功倍 只有光头才能变强! 本文章主要讲的是Java多线程加锁机制,有两种: Synchro ...

  4. Java锁Synchronized对象锁和类锁区别

    java的内置锁:每个java对象都可以用做一个实现同步的锁,这些锁成为内置锁.线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法时会释放该锁.获得内置锁的唯一途径就是进入这个锁的保 ...

  5. 锁对象-条件对象-synchronized关键字

    1 import java.util.concurrent.locks.Condition; 2 import java.util.concurrent.locks.Lock; 3 import ja ...

  6. Java锁 到底锁的是哪个对象?

    更新:在一次和一位专家的交谈中,他对一下代码能否能够成功同步,给予了否定的答案, 他的理由是”以构造函数的成员变量作为synchronized的锁,在多线程的情况下,每一个线程都持有自己私有变量的锁, ...

  7. Java:使用synchronized和Lock对象获取对象锁

    在并发环境下,解决共享资源冲突问题时,可以考虑使用锁机制. 1.对象的锁 所有对象都自动含有单一的锁. JVM负责跟踪对象被加锁的次数.如果一个对象被解锁,其计数变为0.在任务(线程)第一次给对象加锁 ...

  8. Java虚拟机14:Java对象大小、对象内存布局及锁状态变化

    一个对象占多少字节? 关于对象的大小,对于C/C++来说,都是有sizeof函数可以直接获取的,但是Java似乎没有这样的方法.不过还好,在JDK1.5之后引入了Instrumentation类,这个 ...

  9. Java虚拟机18:Java对象大小、对象内存布局及锁状态变化

    一个对象占多少字节? 关于对象的大小,对于C/C++来说,都是有sizeof函数可以直接获取的,但是Java似乎没有这样的方法.不过还好,在JDK1.5之后引入了Instrumentation类,这个 ...

随机推荐

  1. windows 下的 Apache 二级域名 目录绑定配置

    通常我们注册的域名都是顶级域名  如 www.potatog.com,我们希望这个域名可以访问服务器的不同网站或者不同功能等等 可能会这样 www.potatog.com/api 或者 www.pot ...

  2. @总结 - 7@ 生成树计数 —— matrix - tree 定理(矩阵树定理)与 prüfer 序列

    目录 @0 - 参考资料@ @0.5 - 你所需要了解的线性代数知识@ @1 - 矩阵树定理主体@ @证明 part - 1@ @证明 part - 2@ @证明 part - 3@ @证明 part ...

  3. 模板—点分治A(容斥)(洛谷P2634 [国家集训队]聪聪可可)

    洛谷P2634 [国家集训队]聪聪可可 静态点分治 一开始还以为要把分治树建出来……• 树的结构不发生改变,点权边权都不变,那么我们利用刚刚的思路,有两种具体的分治方法.• A:朴素做法,直接找重心, ...

  4. spark.read.csv读取CSV文件 ArrayIndexOutOfBoundsException报错

    通过 spark.read.csv读取CSV文件时,遇到 到 ArrayIndexOutOfBoundsException报错,初步判断是缺少参数导致,放百度看看,没找引起问题相关的参数. 第一个看到 ...

  5. js常见运算符

    博客地址 :https://www.cnblogs.com/sandraryan/

  6. 弹性FLEX布局

    页面布局一直都是web应用样式设计的重点 我们传统的布局方式都是基于盒模型的 利用display.position.float来布局有一定局限性 比如说实现自适应垂直居中 随着响应式布局的流行,CSS ...

  7. mybatis 嵌套查询与懒加载

    懒加载:对于页面有很多静态资源的情况下(比如网商购物页面),为了节省用户流量和提高页面性能,可以在用户浏览到当前资源的时候,再对资源进行请求和加载. fetchType="lazy" ...

  8. set_time_limit(0)是什么意思?

    语法 : void set_time_limit (int seconds) 说明 : 设定一个程式所允许执行的秒数,如果到达限制的时间,程式将会传回错误.它预设的限制时间是30秒,max_execu ...

  9. hibernate无限递归问题

    项目异常如下: 2018-01-26 17:12:38.162 WARN 3128 --- [nio-8080-exec-6] .w.s.m.s.DefaultHandlerExceptionReso ...

  10. 从零开始学习Kafka

    简介 kafka是一个分布式消息队列.具有高性能.持久化.多副本备份.横向扩展能力.生产者往队列里写消息,消费者从队列里取消息进行业务逻辑.一般在架构设计中起到解耦.削峰.异步处理的作用. Kafka ...