首先是简单的自旋锁代码实现:
package org.cc.concur;
public class MyLock {
public MyLock() {
}
private boolean isLocked=false;
public synchronized void lock() throws InterruptedException{
while(isLocked){
System.out.println(Thread.currentThread().getName()+"堵塞了");
wait();
}
isLocked=true;
System.out.println(Thread.currentThread().getName()+"正在运行");
Thread.currentThread().sleep(1000);
}
public synchronized void unlock(){
isLocked=false;
notifyAll();
}
}
这是一个最简单的自旋锁
有如下特点:
- 不支持重入
- 任一非锁定线程执行unlock都会导致锁失效(这个是操作相关的)
以上的特点用如下代码来测试:
// 正常使用情况
public void testLock() throws InterruptedException{
final MyLock lock=new MyLock();
Thread thread=new Thread(new Runnable(){
@Override
public void run(){
try{
lock.lock();
System.out.println("-------1线程正在运行");
Thread.sleep(1000);
System.out.println("-------1线程运行结束。。。。。。");
}catch(Exception e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
}, "线程2");
thread.start();
lock.lock();
System.out.println("-------主线程正在运行");
Thread.sleep(1000);
System.out.println("-------主线程运行结束。。。。。。");
lock.unlock();
}
输出:
main正在运行
-------主线程正在运行
线程1堵塞了
-------主线程运行结束。。。。。。
线程1正在运行
// 非锁定线程使用了unlock
Thread thread=new Thread(new Runnable(){
@Override
public void run(){
try{
lock.unlock();
lock.lock();
System.out.println("-------1线程正在运行");
Thread.sleep(1000);
System.out.println("-------1线程运行结束。。。。。。");
}catch(Exception e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
}, "线程1");
这样可以看出 任何的非锁定线程的线程都可以解开锁
main正在运行
-------主线程正在运行
线程1正在运行
-------主线程运行结束。。。。。。
-------1线程正在运行
最后一种就是重入的情况:
lock.lock();
lock.lock();
System.out.println("-------主线程正在运行");
Thread.sleep(1000);
System.out.println("-------主线程运行结束。。。。。。");
lock.unlock();
输出:
main正在运行
main堵塞了
线程1堵塞了
以上的地方改进很简单
设置一个属性保存进入的线程对象 并进行一些判断
以上一些缺点共同写入了代码:
package org.cc.concur;
public class MyLockReentranceLock {
public MyLockReentranceLock() {
}
private boolean isLocked=false;
private int count=0;
private Object currentThread=null;
public synchronized void lock() throws InterruptedException{
while(isLocked&&Thread.currentThread()!=currentThread){
System.out.println(Thread.currentThread().getName()+"堵塞了");
wait();
}
currentThread=Thread.currentThread();
if(count==0){
isLocked=true;
}
count++;
System.out.println(Thread.currentThread().getName()+"正在运行");
Thread.sleep(1000);
}
public synchronized void unlock(){
if(Thread.currentThread()==currentThread){
count--;
System.out.println("---状态:"+Thread.currentThread().getName()+": "+count);
}
if(count==0){
isLocked=false;
currentThread=null;
System.out.println(Thread.currentThread().getName()+"-----解放了锁");
notifyAll();
}
}
public static void main(String []args) throws InterruptedException{
final MyLockReentranceLock lock=new MyLockReentranceLock(); // 支持重入
Thread thread=new Thread(new Runnable(){
@Override
public void run(){
try{
lock.lock();
System.out.println("-------1线程正在运行");
Thread.sleep(1000);
System.out.println("-------1线程运行结束。。。。。。");
}catch(Exception e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
}, "线程1");
Thread thread2=new Thread(new Runnable(){
@Override
public void run(){
try{
lock.unlock();
lock.lock();
System.out.println("-------2线程正在运行");
Thread.sleep(1000);
System.out.println("-------2线程运行结束。。。。。。");
}catch(Exception e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
}, "线程2");
thread2.start();
thread.start();
lock.lock();
lock.lock();
System.out.println("主线程正在运行。。。。。");
Thread.sleep(1000);
System.out.println("主线程运行结束。。。。。。");
lock.unlock();
lock.unlock();
}
}
一次运行时的情况:
main正在运行
main正在运行
主线程正在运行。。。。。
线程1堵塞了
线程2堵塞了
主线程运行结束。。。。。。
---状态:main: 1
---状态:main: 0
main-----解放了锁
线程2正在运行
-------2线程正在运行
线程1堵塞了
-------2线程运行结束。。。。。。
---状态:线程2: 0
线程2-----解放了锁
线程1正在运行
-------1线程正在运行
-------1线程运行结束。。。。。。
---状态:线程1: 0
线程1-----解放了锁