synchronized 和 lock 基本使用以及死锁分析
来源:互联网 发布:百度域名 编辑:程序博客网 时间:2024/06/07 03:24
1.未加锁
多线程程序未加锁可能产生安全问题
线程未加锁可能造成数据重复访问
如下程序
public class SellTickets implements Runnable{ private int ticketNumber = 100; @Override public void run() { while(true){ if(ticketNumber > 0){ System.out.println(Thread.currentThread().getName()+"正在出售第"+ ticketNumber-- +"张票"); } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { SellTickets seller = new SellTickets(); Thread seller1 = new Thread(seller,"售票员1"); Thread seller2 = new Thread(seller,"售票员2"); Thread seller3 = new Thread(seller,"售票员3"); seller1.start(); seller2.start(); seller3.start(); }}
Console
2.使用synchronized加锁
synchronized特性:
一 : 采用synchronized修饰符实现的同步机制叫做互斥锁机制,它所获得的锁叫做互斥锁。每个对象的锁只能分配给一个线程,因此叫做互斥锁
二 :类的每个实例都有自己的对象级别锁。当一个线程访问实例对象中的synchronized同步代码块或同步方法时,该线程便获取了该实例的对象级别锁,其他线程这时如果要访问synchronized同步代码块或同步方法,便需要阻塞等待,直到前面的线程从同步代码块或方法中退出,释放掉了该对象级别锁
三 :访问同一个类的不同实例对象中的同步代码块,不存在阻塞等待获取对象锁的问题,因为它们获取的是各自实例的对象级别锁,相互之间没有影响。
为synchronized指定代码块加锁(该代码块一个线程访问时,其他线程无法同时访问此块代码)
synchronized ((同步对象一般用)this) { //指定代码块 //锁对象可以是任意对象(但须确保为同一对象才能保证数据加锁) }
synchronized修饰方法,则该方法内所有代码加锁
若synchronized需加锁为静态方法一般采用则使用类名.class作为参数
3.使用Lock加锁
lock特征:
Lock实现提供比使用synchronized方法和语句可以获得的更广泛的锁定操作。 它们允许更灵活的结构化,可能具有完全不同的属性,并且可以支持多个相关联的对象Condition 。
所有已知实现类:
ReentrantLock( 重入锁), ReentrantReadWriteLock.ReadLock (读锁), ReentrantReadWriteLock.WriteLock (写锁)
本文将使用ReentrantLock实现类来为线程加锁,需要注意,锁对象解锁需要在finally语句块中,
ReentrantLock lock = new ReentrantLock(); while(true){ try{ lock.lock(); if(ticketNumber > 0){ System.out.println(Thread.currentThread().getName()+"正在出售第"+ ticketNumber-- +"张票"); } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } finally{ lock.unlock(); } }
4.死锁问题
如果出现了同步嵌套,就容易产生死锁问题
是指两个或者两个以上的线程在执行的过程中,因争夺资源产生的一种互相等待现象
可以理解为A线程访问某B线程正在访问的对象过程中,B线程同时访问A所访问的对象,相互加锁,无法正常运行
同步代码块的嵌套案例
public class DieLockDemo extends Thread{ //创建两把锁对象 public static final Object obj1 = new Object(); public static final Object obj2 = new Object(); private boolean flag = false; public DieLockDemo(String name ,boolean flag) { super(name); this.flag = flag; } @Override public void run() { while(true){ if(flag){ synchronized (obj1) { System.out.println(getName()+" use obj1"); synchronized (obj2) { System.out.println(getName()+" use obj2"); } } } else { synchronized (obj2) { System.out.println(getName()+" use obj1"); synchronized (obj1) { System.out.println(getName()+" use obj2"); } } } } } public static void main(String[] args) { DieLockDemo d1 = new DieLockDemo("小王", true); DieLockDemo d2 = new DieLockDemo("小强", false); d1.start(); d2.start(); }}
- synchronized 和 lock 基本使用以及死锁分析
- synchronized 和 Lock基本用法
- synchronized和lock以及synchronized和volatile的区别
- Java学习-Lock机制和Synchronized分析
- Lock和synchronized的区别和使用
- Lock和synchronized的区别和使用
- synchronized和lock的区别和使用
- Lock和synchronized的区别和使用
- Java中Synchronized和Lock的使用
- Java中Synchronized和Lock的使用
- Java中Synchronized和Lock的使用
- Java中Synchronized和Lock的使用
- 使用lock 产生死锁
- java并发之BlockingQueue和Lock以及synchronized
- 使用synchronized产生死锁
- 使用synchronized实现死锁
- 锁 synchronized和Lock
- synchronized 和 Lock
- Vmware12 安装centos6.5 64位(centos-6.5-x86_64-bin-DVD1.iso)出错
- Unsupervised Domain Adaptation with Residual Transfer Networks(2017)
- 新概念4-14
- Centos6.5安装Tengine
- 机器学习知识点
- synchronized 和 lock 基本使用以及死锁分析
- Anaconda4.3.1安装opencv3
- 《数据结构学习与实验指导》2-2:数组元素循环右移问题
- Qt播放音视频文件
- 淘淘商城系列——导入商品数据到索引库——Service层
- MATLAB双目标定——棋盘格左右图像自动保存MATLAB程序
- JAVA学习笔记——BigInteger类和BigDecimal类
- 三大指针:行指针、指针数组、二级指针
- PHP定界符{}的作用