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 ...
随机推荐
- C# 执行DOS命令和批处理
在项目开发中,有时候要处理一些文件,比如视频格式的转换,如果用C开发一套算法,再用C#调用,未免得不偿失!有时候调用现有的程序反而更加方便.今天就来说一下C#中如何调用外部程序,执行一些特殊任务. 这 ...
- 剑指Offer_编程题_19
题目描述 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2, ...
- 主机管理+堡垒机系统开发:webssh(十)
一.安装shellinabox 1.安装依赖工具 yum install git openssl-devel pam-devel zlib-devel autoconf automake libtoo ...
- HTML多图片压缩上传
本文介绍的是多张图片在前端统一压缩后再通过ajax提交给后台处理的业务,使用到的是LocalResizeIMG.js插件. 一.首先介绍项目结构 二.分享引用核心文件,这里没有分享CSS文件,因为没有 ...
- 第十三节: EF的三种模式(三) 之 来自数据库的CodeFirst模式
一. 简介 [来自数据库的Code First模式]实质上并不是CodeFirst模式,而是DBFirst模式的轻量级版本,在该模式中取消了edmx模型和T4模板,直接生成了EF上下文和相应的类,该模 ...
- 通过IDEA搭建scala开发环境开发spark应用程序
一.idea社区版安装scala插件 因为idea默认不支持scala开发环境,所以当需要使用idea搭建scala开发环境时,首先需要安装scala插件,具体安装办法如下. 1.打开idea,点击c ...
- 排序算法以及其java实现
一.术语了解 稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面: 不稳定:如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面: 内排序:所有排序操作都在内存中完成: 外排序:由 ...
- day02 解释器安装及初识变量
今日内容: 1.解释器的安装 2.添加到环境变量 3.pip初识 4.变量初识 5.PyCharm安装及激活 今日重点: 1.将python及pip添加到环境变量 在将python解释器安装到计算机后 ...
- tomcat 优化建议
下面给出的是tomcat的优化建议,如果不同意见请留言. 上配置: tomcat jmx配置访问:修改catalina.sh CATALINA_OPTS="$CATALINA_OPTS -D ...
- C# 微信开发-----微信会员卡(三)激活会员卡
在会员领取了会员卡之后需要做 一个跳转性激活,模式请看下图: 在创建会员卡的时候需要配置下这个参数的值: memberActivate.aspx页面代码如下: <%@ Page Language ...