锁对象

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

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. 开发者说:如何参与定义一款 IDE 插件

    摘要: If not now,when? If not you,who?共同定义 Cloud Toolkit 的未来! 自从产品经理银时小伙和他的开发小哥们在去年12月发布 Cloud Toolkit ...

  2. 【Android内存机制分析】了解Android堆和栈

    昨天用Gallery做了一个图片浏览选择开机画面的功能,当我加载的图片多了就出现OOM问题.以前也出现过这个问题,那时候并没有深究.这次打算好好分析一下Android的内存机制. 因为我以前是做VC+ ...

  3. hdu 2662 Coin

    Coin Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  4. JQuery完整验证&密码的显示与隐藏&验证码

    HTML <link href="bootstrap.css" rel="stylesheet"> <link href="gloa ...

  5. react组件之间的参数传递

    1.父组件向子组件传递参数 class Child extends Component { componentDidMount(){ let name = this.props.default; co ...

  6. H3C 广域网连接方式

  7. Flex AIR应用拍照功能(Android和IOS版本)

    说明: 使用AIR处理拍照后的回调.照片文件的保存功能时,针对于IOS和Android两个平台是有所不同的. 但.关于如何调用摄像头进行拍照这个功能,Android和IOS是一致的. 技术实现: 1) ...

  8. jstack简介

    jstack:Java进程中线程的堆栈信息跟踪工具 功能简介 jstack常用来打印Java进程/core文件/远程调试端口的Java线程堆栈跟踪信息,包含当前虚拟机中所有线程正在执行的方法堆栈信息的 ...

  9. PC端页面如何调用QQ进行在线聊天?

    pc端如何实现QQ在线咨询? html代码如下: <a href="tencent://message/?uin=1234567&Site=Sambow&Menu=ye ...

  10. CodeForces 242E "XOR on Segment"(线段树)

    传送门 •题意 给你一个包含 n 个数的序列 a,定义序列上的两个操作: (1)$1,l,r\ :\ ans=\sum_{i=l}^{r}a_i$; (2)$2,l,r,x\ :\ \forall\ ...