java多线程 -- 同步鎖
为了解决多线程安全问题
在 Java 5.0 之前,协调共享对象的访问时可以使用的机制只有 synchronized 和 volatile 。
Java 5.0 后增加了一些新的机制,但并不是一种替代内置锁的方法,而是当内置锁不适用时,作为一种可选择的高级功能。
隐式锁
synchronized
- 同步代码块;
- 同步方法。
显示锁 Lock
jdk 1.5 后:同步锁 Lock 需要通过 lock() 方法上锁,必须通过 unlock() 方法进行释放锁。
ReentrantLock 实现了 Lock 接口,并提供了与synchronized 相同的互斥性和内存可见性。但相较于synchronized 提供了更高的处理锁的灵活性。
Lock使用方式:
- Lock lock = new ReentrantLock();
- lock.lock();
- try {
- } finally {
- lock.unlock();
- }
相关API:
- void lock() 获取锁。
- void lockInterruptibly() 如果当前线程未被中断,则获取锁。
- Condition newCondition() 返回绑定到此 Lock 实例的新 Condition 实例。
- boolean tryLock() 仅在调用时锁为空闲状态才获取该锁。
- boolean tryLock(long time, TimeUnit unit) 如果锁在给定的等待时间内空闲,并且当前线程未被中断,则获取锁。
- void unlock()释放锁。
不使用锁出现多线程安全问题demo:
- package com.company;
- public class TestLock {
- public static void main(String[] args) {
- Ticket ticket = new Ticket();
- new Thread(ticket, "1号窗口").start();
- new Thread(ticket, "2号窗口").start();
- new Thread(ticket, "3号窗口").start();
- }
- }
- class Ticket implements Runnable{
- private int tick = 100;
- @Override
- public void run() {
- while(true){
- if(tick > 0){
- try {
- Thread.sleep(200);
- } catch (InterruptedException e) {
- }
- System.out.println(Thread.currentThread().getName() + " 完成售票,余票为:" + --tick);
- }
- }
- }
- }
看出现的问题(截取结果中一部分):
- 3号窗口 完成售票,余票为:10
- 1号窗口 完成售票,余票为:8
- 2号窗口 完成售票,余票为:8
- 3号窗口 完成售票,余票为:8
- 2号窗口 完成售票,余票为:7
- 1号窗口 完成售票,余票为:7
- 3号窗口 完成售票,余票为:7
- 1号窗口 完成售票,余票为:6
- 2号窗口 完成售票,余票为:5
- 3号窗口 完成售票,余票为:4
- 3号窗口 完成售票,余票为:3
- 1号窗口 完成售票,余票为:3
- 2号窗口 完成售票,余票为:3
- 3号窗口 完成售票,余票为:2
- 1号窗口 完成售票,余票为:0
- 2号窗口 完成售票,余票为:1
现在我们用Lock来进行处理:
- package com.company;
- import java.util.concurrent.locks.Lock;
- import java.util.concurrent.locks.ReentrantLock;
- public class TestLock {
- public static void main(String[] args) {
- Ticket ticket = new Ticket();
- new Thread(ticket, "1号窗口").start();
- new Thread(ticket, "2号窗口").start();
- new Thread(ticket, "3号窗口").start();
- }
- }
- class Ticket implements Runnable {
- private int tick = 100;
- private Lock lock = new ReentrantLock();
- @Override
- public void run() {
- while (true) {
- try {
- lock.lock();
- if (tick > 0) {
- try {
- Thread.sleep(200);
- } catch (InterruptedException e) {
- }
- System.out.println(Thread.currentThread().getName() + " 完成售票,余票为:" + --tick);
- }
- } finally {
- lock.unlock();
- }
- }
- }
- }
看下结果(当然也是一部分),很完美解决多线程安全问题:
- 2号窗口 完成售票,余票为:20
- 2号窗口 完成售票,余票为:19
- 2号窗口 完成售票,余票为:18
- 2号窗口 完成售票,余票为:17
- 2号窗口 完成售票,余票为:16
- 2号窗口 完成售票,余票为:15
- 2号窗口 完成售票,余票为:14
- 2号窗口 完成售票,余票为:13
- 2号窗口 完成售票,余票为:12
- 2号窗口 完成售票,余票为:11
- 2号窗口 完成售票,余票为:10
- 2号窗口 完成售票,余票为:9
- 2号窗口 完成售票,余票为:8
- 2号窗口 完成售票,余票为:7
- 2号窗口 完成售票,余票为:6
- 2号窗口 完成售票,余票为:5
- 2号窗口 完成售票,余票为:4
- 2号窗口 完成售票,余票为:3
- 2号窗口 完成售票,余票为:2
- 2号窗口 完成售票,余票为:1
- 2号窗口 完成售票,余票为:0
java多线程 -- 同步鎖的更多相关文章
- Java多线程同步问题的探究
一.线程的先来后到——问题的提出:为什么要有多线程同步?Java多线程同步的机制是什么? http://www.blogjava.net/zhangwei217245/archive/2010/03/ ...
- 转:关于JAVA多线程同步
转:http://lanvis.blog.163.com/blog/static/26982162009798422547/ 因为需要,最近关注了一下JAVA多线程同步问题.JAVA多线程同步主要依赖 ...
- java多线程同步
一篇好文:java多线程机制同步原则 概括起来说,Java 多线程同步机制主要包含如下几点:1:如果一个类包含一个或几个同步方法,那么由此类生成的每一个对象都配备一个队列用来容纳那些等待执行同步的线程 ...
- Java多线程-同步:synchronized 和线程通信:生产者消费者模式
大家伙周末愉快,小乐又来给大家献上技术大餐.上次是说到了Java多线程的创建和状态|乐字节,接下来,我们再来接着说Java多线程-同步:synchronized 和线程通信:生产者消费者模式. 一.同 ...
- Java多线程同步 synchronized 关键字的使用
代表这个方法加锁,相当于不管哪一个线程A每次运行到这个方法时,都要检查有没有其它正在用这个方法的线程B(或者C D等),有的话要等正在使用这个方法的线程B(或者C D)运行完这个方法后再运行此线程A, ...
- Java多线程---同步与锁
一,线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏. 二.同步和锁定 1.锁的原理 Java中每个对象都有一个内置锁. 当程序运行到非静态的synchronized同步方法上时,自动 ...
- Java多线程同步的方法
一 synchronized关键字 1.synchronized实现原理: ---基于对象监视器(锁) java中所有对象都自动含有单一的锁,JVM负责跟踪对象被加锁的次数.如果一个对象被解锁,其计数 ...
- Java 多线程同步的五种方法
一.引言 闲话不多说,进入正题. 二.为什么要线程同步 因为当我们有多个线程要同时访问一个变量或对象时,如果这些线程中既有读又有写操作时,就会导致变量值或对象的状态出现混乱,从而导致程序异常.举个例子 ...
- Java多线程同步问题:一个小Demo完全搞懂
版权声明:本文出自汪磊的博客,转载请务必注明出处. Java线程系列文章只是自己知识的总结梳理,都是最基础的玩意,已经掌握熟练的可以绕过. 一.一个简单的Demo引发的血案 关于线程同步问题我们从一个 ...
随机推荐
- JavaScript学习笔记(七)—— 再说函数
第八章 函数 1 函数声明和函数表达式 差别一:函数声明:函数在执行代码前被创建:函数表达式是在运行阶段执行代码时创建: 差别二:函数声明创建一个与函数同名的变量,并让她指向函数:使用函数表达式,不给 ...
- git查看添加删除远程仓库
查看远程仓库 git remote -v 删除远程仓库 git remote remove origin 添加远程仓库 git remote add origin 仓库地址 关联远程分支 重新关联远程 ...
- 君学,佳一tvodp文件破解
tvodp文件破解的意思就是,越过加密部分直接提取内部原始文件,难度较大,方法用U盘刻老毛桃pe,然后电脑启动pe,在pe中打开文件,做提取工作, 本人淘宝破解:https://item.taobao ...
- Django_WSGIRequest对象
WSGIRequest对象 Django在接收到http请求之后,会根据http请求携带的参数以及报文信息创建一个WSGIRequest对象,并且作为视图函数第一个参数传给视图函数.这个参数就是dja ...
- Scrum Meeting 10.25
成员 已完成任务 下一阶段任务 用时 徐越 阅读前端代码中和通信相关的部分 学习服务器配置 4h 赵庶宏 阅读前端代码中和通信相关的部分 学习服务器配置 4h 薄霖 继续做UI开发 界面优化 4h 武 ...
- 2-Third Scrum Meeting-20151203
任务安排 闫昊: 今日完成:请假.(编译+计组,压力有点大) 明日任务:设计本地数据库. 唐彬: 今日完成:请假.(编译+计组,压力有点大) 明日任务:阅读ios客户端代码. 史烨轩: 今日完成:请假 ...
- 2018-2019-20172329 《Java软件结构与数据结构》第七周学习总结
2018-2019-20172329 <Java软件结构与数据结构>第七周学习总结 教材学习内容总结 <Java软件结构与数据结构>第十一章-二叉查找树 一.概述 1.什么是二 ...
- poi读取、通过poi导出数据库的记录到excl表
package com.nt.test; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFo ...
- asp.net 错误24
错误 24 “xxx.Web.xxx.xxx”不包含“xxName”的定义,并且找不到可接受类型为“xxx.Web.xxxr.xxx”的第一个参数的扩展方法“xxxName”(是否缺少 using 指 ...
- printf in KEIL C51
转自:http://blog.csdn.net/it1988888/article/details/8821713 在keil中printf默认是向串口中发送数据的,所以,如果应用该函数,必须先初始化 ...