第一種方法:採用公平鎖實現
思路及其簡單:
- A線程拿到鎖,執行代碼
- B線程拿到鎖,執行代碼
- A線程拿到鎖,執行代碼
- ......
public class FairLockDemo {
public static void main(String[] args) {
Runnable target = new Runnable(){
int i = 10;
// 利用公平鎖
private ReentrantLock lock = new ReentrantLock(true);
@Override
public void run() {
while (i >= 0) {
try{
lock.lock();
if(i % 2 == 0){
System.out.println("A");
}else {
System.out.println("B");
}
i--;
}finally{
lock.unlock();
}
}
}
};
Thread t1 = new Thread(target, "thread-1");
Thread t2 = new Thread(target, "thread-2");
t1.start();
t2.start();
}
}
第二種方法:採用synchronized對象鎖 + wait + notify實現
思路比較複雜,值得細細揣摩:
- 關鍵點:每個線程都有獲得鎖的權利
- 1、滿足if條件的,wait等待釋放鎖
- 2、不滿足if條件的,執行業務代碼
public class TestThead {
// 對象鎖
private static Object obj = new Object();
private static volatile int num = 10;
public static void main(String[] args) {
new Thread(new Runnable() { // 匿名內部類
@Override
public void run() {
synchronized (obj) {
while(num > 0){
if(num % 2 == 0){
try {
obj.wait(); // 釋放鎖進入等待隊列(等待池),線程2獲取到對象鎖
} catch (InterruptedException e) {
e.printStackTrace();
}
}
num--;
if(num >= 0){
System.out.println("B");
}
obj.notify(); // 喚醒等待隊列中線程2進入鎖池競爭對象鎖
}
}
}
}, "thread1").start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (obj) {
while(num > 0){
if(num % 2 != 0){
try {
obj.wait(); // 釋放鎖進入等待隊列(等待池),線程1獲取到對象鎖
} catch (InterruptedException e) {
e.printStackTrace();
}
}
num--;
if(num >= 0){
System.out.println("A");
}
obj.notify(); // 喚醒等待隊列中線程1進入鎖池競爭對象鎖
}
}
}
}, "thread2").start();
}
}
3、採用Lock和Condition實現
思路:
- 其實和上面的思路差不多
- 只不過上面用了同一個對象鎖,思考起來比較麻煩
- 這裏採用了兩個鎖,輪流開閉,思考起來很方便
public class LockCond {
private static volatile int count = 10;
private static Lock lock = new ReentrantLock();
public static void main(String[] args) {
Condition c1 = lock.newCondition();
Condition c2 = lock.newCondition();
new Thread(()->{
while(count > 0) {
lock.lock();
try {
if(count % 2 == 0) {
System.out.println("A");
c1.await();
}
//喚醒線程2
c2.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
count--;
lock.unlock();
}
}
}) .start();
new Thread(()->{
while(count > 0) {
lock.lock();
try {
if(count % 2 == 1) {
System.out.println("B");
c2.await();
}
//喚醒線程1
c1.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
count--;
lock.unlock();
}
}
}) .start();
}
}