您的位置:首页 > 编程语言 > Java开发

synchronized 和 lock 基本使用以及死锁分析

2017-06-07 00:39 429 查看

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();

}
}


b0c4
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息