十一、併發程式設計之Lock介面的認識與使用
阿新 • • 發佈:2019-01-03
1、認識
2、優勢
- Lock 類似於synchronized,具有相同的互斥性和記憶體可見性,但是更加靈活,加鎖和放鎖可以由使用者自己確定,Synchronized不需要顯示地獲取和釋放鎖,簡單
- 可以方便的實行公平性
- 非阻塞的獲取鎖
- 能被中斷的獲取鎖,synchronized鎖可能出現異常而導致中斷,無法釋放鎖,但是通過使用lock,可以直接將lock放在異常finally中,強制釋放鎖。
- 超時獲取鎖
3、使用
public class Sequence {
private int value ;
Lock lock = new ReentrantLock();
public int getNext() {
//lock放在這裡是鎖不住的,所有執行緒得共用一把鎖才鎖的住,所有鎖得放外邊
//Lock lock = new ReentrantLock();
lock.lock();//獲取鎖
int a = value++;
lock.unlock();//釋放鎖
return a;
}
public static void main(String[] args) {
Sequence sequence = new Sequence();
//第一個執行緒
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
System.out.println(Thread.currentThread().getName()+" ----->"+sequence.getNext());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
//第二個執行緒
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
System.out.println(Thread.currentThread().getName()+" ----->"+sequence.getNext());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
//第三個執行緒
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
System.out.println(Thread.currentThread().getName()+" ----->"+sequence.getNext());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
4、實現一個普通的鎖
public class MyLock implements Lock{
private boolean isLocked = false;
//加鎖
@Override
public synchronized void lock() {
// 第一個執行緒進來不等待,其他線性進來等待
while(isLocked) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
isLocked = true;
}
//釋放鎖
@Override
public synchronized void unlock() {
isLocked = false;//釋放鎖
notifyAll();//喚醒其他執行緒
}
//中斷鎖
@Override
public void lockInterruptibly() throws InterruptedException {
}
@Override
public boolean tryLock() {
return false;
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return false;
}
@Override
public Condition newCondition() {
return null;
}
}
public class Sequence {
private MyLock lock = new MyLock();
private int value;
public int getNext() {
lock.lock();//獲取鎖
value++;
lock.unlock();//釋放鎖
return value;
}
public static void main(String[] args) {
Sequence sequence = new Sequence();
//第一個執行緒
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
System.out.println(Thread.currentThread().getName()+" ----->"+sequence.getNext());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
//第二個執行緒
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
System.out.println(Thread.currentThread().getName()+" ----->"+sequence.getNext());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
//第三個執行緒
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
System.out.println(Thread.currentThread().getName()+" ----->"+sequence.getNext());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
5、實現一個重入鎖
public class MyLock implements Lock {
private boolean isLocked = false;//是否鎖住
private Thread lockBy = null;//拿到鎖的執行緒
private int lockCount = 0;//鎖的數量
@Override
public synchronized void lock() {
Thread currentThread = Thread.currentThread(); // 當前執行緒
while (isLocked && currentThread != lockBy)//鎖住了並且執行緒不等於當前執行緒
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
isLocked = true;
lockBy = currentThread;
lockCount ++; // 1 2 3拿到鎖的數量想加
}
@Override
public synchronized void unlock() {
if(lockBy == Thread.currentThread()) {
lockCount --; //2 1 0
if(lockCount == 0) {//釋放所有鎖之後
notify();
isLocked = false;
}
}
}
@Override
public void lockInterruptibly() throws InterruptedException {
}
@Override
public boolean tryLock() {
return false;
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return false;
}
@Override
public Condition newCondition() {
return null;
}
}
public class Demo {
MyLock lock = new MyLock();
public void a() {
lock.lock();
System.out.println("a");
b();
lock.unlock();
}
public void b() {
lock.lock();
System.out.println("b");
c();
lock.unlock();
}
public void c() {
lock.lock();
System.out.println("c");
lock.unlock();
}
public static void main(String[] args) {
Demo d = new Demo();
new Thread(new Runnable() {
@Override
public void run() {
d.a();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
d.b();
}
}).start();
}
}