Lock锁方式解决线程安全问题
在JDK5.0之后新增加了一种更强大的线程同步机制---通过显示定义同步锁来实现线程同步解决线程安全问题。同步锁使用Lock对象充当。
java.util.concurrent.locks.lock接口是控制多个线程对共享资源进行访问的工具。锁提供了对共享资源的单独访问,每一次只能有一个线程对Lock对象加锁,并且线程在访问共享资源之前应该先加锁。
ReentrantLock类实现了Lock,它拥有和synchronized相同的并发行和内存语义,在实现线程安全的控制中,比较常用的就是ReentrantLock,可以实现显示的加锁和释放锁,比较灵活。
使用Lock锁的方式模拟多线程共同卖票的情景:
package com.baozi.java; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class WinowTest4 {
public static void main(String[] args) {
Window4 w1 = new Window4();
Window4 w2 = new Window4();
Window4 w3 = new Window4();
w1.start();
w2.start();
w3.start();
}
} //通过继承Thread类的方法来实现多线程
class Window4 extends Thread {
private static int ticket = 100;
private static Lock lock = new ReentrantLock(); @Override
public void run() {
while (true) {
try {
lock.lock();
if (ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + ticket--);
} else {
break;
}
} finally {
lock.unlock();
} }
}
}
synchronized和Lock 的异同:
同:两者都是解决线程安全问题
异:
- synchronized关键字定义的不管是同步代码块还是同步方法在执行完成之后都是自动的释放同步监视器(这是一种隐式锁,出了作用域隐式锁将自动的释放)
- lock需要手动的上锁启动同步和手动解锁结束同步;
- Lock只有代码块锁,没办法对某一方法上锁
- Lock锁比较灵活,JVM只需要花费较小的代价来实现线程的调度,性能更好并且有更好的扩展性;
这是一个应用实例:
有两个用户,分三次往同一个账户中存钱,每次每一个人都是存1000元。
分析:
- 是否是多线程问题:是,两个用户是两个线程
- 是否有共享数据:账户余额
- 是否有线程安全问题:有,当两个线程同时往里边存钱时候,如果不进行安全控制,账户余额会出现错误
- 所以考虑使用同步机制解决线程安全问题
package com.baozi.exer; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; /**
* 银行有一个账户,两个储户分别向里边存三次钱,每次都存一千元,
*/
public class AccountTest {
public static void main(String[] args) {
Account account = new Account(0);
Customer c1 = new Customer(account);
Customer c2 = new Customer(account);
c2.setName("储户2");
c1.setName("储户1");
c1.start();
c2.start();
}
} class Account {
private int balance;
Lock lock = new ReentrantLock(); public Account(int balance) {
this.balance = balance;
} public void setBalance(int amt) {
lock.lock();
try {
if (amt > 0) {
balance += amt;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " :当前余额为: " + balance);
}
} finally {
lock.unlock();
}
} } class Customer extends Thread { private Account account; public Customer(Account account) {
this.account = account;
} @Override
public void run() {
for (int i = 0; i < 3; i++) {
account.setBalance(1000);
}
}
}
Lock锁方式解决线程安全问题的更多相关文章
- Java之解决线程安全问题的方式三:Lock锁
import java.util.concurrent.locks.ReentrantLock; /** * 解决线程安全问题的方式三:Lock锁 --- JDK5.0新增 * * 1. 面试题:sy ...
- java 22 - 13 多线程之解决线程安全问题的实现方式2
上一章说了,解决线程安全问题的实现方式1是使用同步代码块 同时也知道了,同步代码块的锁对象是任意对象:(Object obj ; Demo d;)这些都行 那么,现在来说解决线程安全问题的实现方式2 ...
- 静态同步方法和解决线程安全问题_Lock锁
静态的同步方法锁对象是谁?不能是thisthis是创建对象之后产生的,静态方法优先于对象静态方法的锁对象是本类的cLass属性-->class文件对象(反射) 卖票案例出现了线程安全问题 卖出了 ...
- 解决线程安全问题_同步方法和解决线程安全问题_Lock锁
解决线程安全问题_同步方法 package com.yang.Test.ThreadStudy; import lombok.SneakyThrows; /** * 卖票案例出现了线程安全的问题 * ...
- java 22 - 12 多线程之解决线程安全问题的实现方式1
从上一章知道了多线程存在着线程安全问题,那么,如何解决线程安全问题呢? 导致出现问题的原因: A:是否是多线程环境 B:是否有共享数据 C:是否有多条语句操作共享数据 上一章的程序,上面那3条都具备, ...
- java线程安全问题以及使用synchronized解决线程安全问题的几种方式
一.线程安全问题 1.产生原因 我们使用java多线程的时候,最让我们头疼的莫过于多线程引起的线程安全问题,那么线程安全问题到底是如何产生的呢?究其本质,是因为多条线程操作同一数据的过程中,破坏了数据 ...
- java并发之如何解决线程安全问题
并发(concurrency)一个并不陌生的词,简单来说,就是cpu在同一时刻执行多个任务. 而Java并发则由多线程实现的. 在jvm的世界里,线程就像不相干的平行空间,串行在虚拟机中.(当然这是比 ...
- 使用Lock接口来解决线程安全的问题
package cn.itcast.demo16.Demo09.Lock;import java.util.concurrent.locks.Lock;import java.util.concurr ...
- java如何解决线程安全问题
方式一:同步代码块 synchroized(同步监视器的对象){需要被同步的代码} package threadtest; //使用同步代码块实现Runable接口的线程 public class R ...
随机推荐
- Vue基础之es6
什么是ECMAScript,以及es6的诞生? 1997年 ECMAScript 1.0 诞生 1999年12月 ECMAScript 3.0诞生,它 是一个巨大的成功,在业界得到了广泛的支持,它奠定 ...
- Entity Framework入门教程(16)---Enum
EF DbFirst模式中的枚举类型使用 这一节介绍EF DbFirst模式中的Enum(枚举类型),CodeFirst模式中的Enum会在以后的EF CoreFirst系列中介绍.EF5中添加了对E ...
- UML建工工具
本篇博文简单介绍一下自己在搜索UML建模工具的过程中收集到的一些信息. 如果想用中文的,可以考虑楚凡科技的Trufun Plato,不过最近好像没有怎么更新了. 很多前辈以前用的是Rational R ...
- [物理学与PDEs]第3章第1节 等离子体
1. 磁流体力学研究等离子体这种导电流体在电磁场中的运动. 2. 任何物质由于 $T, p$ 等条件的不同而可以处于固态.液态.气态 (常见的三种聚集态) 或等离子体. 3. 等离子体就是电离气 ...
- Spring系列(四) 面向切面的Spring
除了IOC外, AOP是Spring的另一个核心. Spring利用AOP解决应用横切关注点(cross-cutting concern)与业务逻辑的分离, 目的是解耦合. 横切关注点是指散布于代码多 ...
- laravel5.4 向闭合函数内部传递参数
laravel 向闭合函数内部传入参数
- 3D Slicer中文教程(一)—下载及安装方法
3D Slicer是用于医学图像信息学,图像处理和三维可视化的开源软件平台. 通过国家卫生研究院和全球开发人员社区的支持,二十多年来,Slicer为医生,研究人员和公众提供了免费,强大的跨平台加工工具 ...
- 让你爱不释手的 Python 模块
 一. logzero 在一个完整的信息系统里面,日志系统是一个非常重要的功能组成部分.它可以记录下系统所产生的所有行为.我们可以使用日志系统所记录的信息为系统进行排错,优化系统的性能,或者根据这些 ...
- Windows server 2012配置WebDeploy发布网站
以前都是使用win2008r2服务器,最近更新了操作系统到WINDOWS 2012,发现以前的做法已经不适用了. win2008r2配置WebDeploy: https://www.cnblogs.c ...
- Mysql --创建用户和授权,备份
权限管理 我们知道我们的最高权限管理者是root用户,它拥有着最高的权限操作.包括select.update.delete.update.grant等操作.那么一般情况在公司之后DBA工程师会创建一个 ...