这个代码保证value++的原子性。
自己实现一把锁:
为什么不支持重入?这个是mylock老的代码。这个while当作if去解读就可以了。
解锁了。
多线程去执行
在Demo中测试重入。
package com.roocon.thread.ta1;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Demo {
//Lock lock = new ReentrantLock();
Lock 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();
}
}
介绍了检测死锁的工具。
wait是在sy的对象上等待,就是mylock对象。
什么时候释放锁:
任何线程进入同步代码块、同步方法之前,必须获得同步监视器的锁定,那么何时会释放这个锁定呢?在程序中,是无法显式释放对同步监视器的锁的,而会在如下几个情况下释放锁。
1、当前线程的同步方法、代码块执行结束的时候释放
2、当前线程在同步方法、同步代码块中遇到break 、 return 终于该代码块或者方法的时候释放。
3、。。。。出现未处理的error或者exception导致异常结束的时候释放
4、。。。。程序执行了 同步对象 wait 方法 ,当前线程暂停,释放锁
==============================================================如下情况不会释放锁=====================================
1、。。。。。。程序调用 Thread.sleep() Thread.yield() 这些方法暂停线程的执行,不会释放。
2、线程执行同步代码块时,其他线程调用 suspend 方法将该线程挂起,该线程不会释放锁 ,所以我们应该避免使用 suspend 和 resume 来控制线程
关于wait和notify:https://blog.csdn.net/djzhao/article/details/79410229
自己实现的锁的代码:
package com.roocon.thread.ta1;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
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(); // Thread-0
while (isLocked && currentThread != lockBy)//已经被锁住了并且当前的线程不是锁的线程
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
isLocked = true;
lockBy = currentThread;
lockCount ++; // 1 2
}
@Override
public synchronized void unlock() {
if(lockBy == Thread.currentThread()) {
lockCount --; // 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 {
// TODO Auto-generated method stub
return false;
}
@Override
public Condition newCondition() {
// TODO Auto-generated method stub
return null;
}
}
业务多个线程同时调用
package com.roocon.thread.ta1;
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 s = new Sequence();
new Thread(new Runnable() {
@Override
public void run() {
while(true)
System.out.println(s.getNext());
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while(true)
System.out.println(s.getNext());
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while(true)
System.out.println(s.getNext());
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while(true)
System.out.println(s.getNext());
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while(true)
System.out.println(s.getNext());
}
}).start();
}
}
测试可重入的锁的代码。
package com.roocon.thread.ta1;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Demo {
//Lock lock = new ReentrantLock();
Lock 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();
}
}
底层是synchronized和wait和notify实现的。