在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锁方式解决线程安全问题的更多相关文章

  1. Java之解决线程安全问题的方式三:Lock锁

    import java.util.concurrent.locks.ReentrantLock; /** * 解决线程安全问题的方式三:Lock锁 --- JDK5.0新增 * * 1. 面试题:sy ...

  2. java 22 - 13 多线程之解决线程安全问题的实现方式2

    上一章说了,解决线程安全问题的实现方式1是使用同步代码块 同时也知道了,同步代码块的锁对象是任意对象:(Object obj ;  Demo d;)这些都行 那么,现在来说解决线程安全问题的实现方式2 ...

  3. 静态同步方法和解决线程安全问题_Lock锁

    静态的同步方法锁对象是谁?不能是thisthis是创建对象之后产生的,静态方法优先于对象静态方法的锁对象是本类的cLass属性-->class文件对象(反射) 卖票案例出现了线程安全问题 卖出了 ...

  4. 解决线程安全问题_同步方法和解决线程安全问题_Lock锁

    解决线程安全问题_同步方法 package com.yang.Test.ThreadStudy; import lombok.SneakyThrows; /** * 卖票案例出现了线程安全的问题 * ...

  5. java 22 - 12 多线程之解决线程安全问题的实现方式1

    从上一章知道了多线程存在着线程安全问题,那么,如何解决线程安全问题呢? 导致出现问题的原因: A:是否是多线程环境 B:是否有共享数据 C:是否有多条语句操作共享数据 上一章的程序,上面那3条都具备, ...

  6. java线程安全问题以及使用synchronized解决线程安全问题的几种方式

    一.线程安全问题 1.产生原因 我们使用java多线程的时候,最让我们头疼的莫过于多线程引起的线程安全问题,那么线程安全问题到底是如何产生的呢?究其本质,是因为多条线程操作同一数据的过程中,破坏了数据 ...

  7. java并发之如何解决线程安全问题

    并发(concurrency)一个并不陌生的词,简单来说,就是cpu在同一时刻执行多个任务. 而Java并发则由多线程实现的. 在jvm的世界里,线程就像不相干的平行空间,串行在虚拟机中.(当然这是比 ...

  8. 使用Lock接口来解决线程安全的问题

    package cn.itcast.demo16.Demo09.Lock;import java.util.concurrent.locks.Lock;import java.util.concurr ...

  9. java如何解决线程安全问题

    方式一:同步代码块 synchroized(同步监视器的对象){需要被同步的代码} package threadtest; //使用同步代码块实现Runable接口的线程 public class R ...

随机推荐

  1. C++-int类型整数超出范围后的处理

    最近做了一道题目: Given a 32-bit signed integer, reverse digits of an integer. Example 1: Input: 123 Output: ...

  2. volative 与处理器的嗅探技术

    在<java并发编程的艺术>这本书中,关于volatile的内存原理本质的描述如下: 有volatile变量修饰共享变量在编译器编译后,后多出一个“lock” 来(lock前缀指令相当于一 ...

  3. (四)Java工程化--Git基础

    GIT学习参考:https://git-scm.com/book/zh/v2 常见命令 git init 初始化项目 git add *.java 添加文件到git版本控制(.java后缀的全部文件) ...

  4. 让你爱不释手的 Python 模块

     一. logzero 在一个完整的信息系统里面,日志系统是一个非常重要的功能组成部分.它可以记录下系统所产生的所有行为.我们可以使用日志系统所记录的信息为系统进行排错,优化系统的性能,或者根据这些 ...

  5. adb.exe 已停止工作解决办法

    最近因为工作原因,接触了下Android Studio,在使用真机调试的时候碰到了adb.exe 已经停止工作的错误. 虽然网上有很多和我一样的教程,但是我觉的还是记录一下自己的情况比较好,毕竟每个人 ...

  6. undefined reference to `pthread_create'

    问题描述: ubuntu 16.04  下  C语言开发环境, 已经添加了头文件#include <pthread.h> 以及在Makefile中添加了 -lpthread,但是编译时仍然 ...

  7. Linux下安装python的gmpy2库及遇到无法定位软件包的解决办法

    gmpy2需要gmp.h &mpfr.h &mpc.h 安装命令: sudo apt-get install libmpfr-dev libmpc-dev  成功之后再输入安装命令: ...

  8. bootstrap 解决弹出窗口(modal) 常见问题

    无法使用键盘esc关闭窗口方法: 首先在modal容器的div中增加属性tabindex="-1",其次设置键盘ESC属性keyboard为true: 方法1:使用js打开窗口时 ...

  9. JS中 typeof,instanceof类型检测方式

    在js中的类型检测目前我所知道的是三种方式,分别有它们的应用场景: 1.typeof:主要用于检测基本类型. typeof undefined;//=> undefined typeof 'a' ...

  10. 用JS实现实时显示系统时间

    废话我就不多说了,直接上图和代码了 效果图: 代码视图: 下面为大家附上代码,复制即可用: <!DOCTYPE html> <html lang="en"> ...