Lock 锁的理解并附带简单实例

Lock 和 synchronized 都能实现锁机制。synchronized是java中的关键字,是系统内置的。关于synchronized,我前几天写了一篇个人心得。。。。。。。。
Lock 的源代码如下:
public interface Lock {
    void lock();
    void lockInterruptibly() throws InterruptedException;
    boolean tryLock();
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
    void unlock();
    Condition newCondition();
}
由此可见Lock是一个接口。
既然已经存在synchronized了,那为什么还要Lock呢?那就需要看下synchronized的特点了。


synchronized锁定对象了,除非异常或者程序执行结束,才会释放锁。如果中间的程序因为其它原因需要等待,其它线程必须等待。有时候我们希望一段时间还没有处理好,就要释放锁。在实际的开发过程中,我们更多的时候希望对锁进行更多的要求,例如尝试加锁,获取锁的状态,在等待锁时设置一个等待时间....


这些lock都能解决.




Lock比Synchronized对于锁有更多的功能。
Synchronized的使用,一般都是定义在方法体上或者定义在方法内部,直接synchronized(?){}。Synchronized不需要程序解锁,程序结束或者出现异常会自动解锁。
Lock有很大的不同,因为Lock是一个接口。我们需要new它的实现类ReentrantLock。Lock必须要手动解锁,为了防止死锁,解锁必须要放到finally体重。
例如


Lock lock = new ReentrantLock();
 lock.lock();
 try{
 // 需要执行的代码
 }catch(Excaption e){
 }finally{
  lock.unlock();
 }




下面通过代码,我全面的测试Lock的所有函数。


 1)lock()函数
public class Main {

 Lock lock = new ReentrantLock();

public static void main(String[] args) {
new TestThread().start();
new TestThread().start();
new TestThread().start();
}
public  void test(){


lock.lock();
try{
System.out.println(Thread.currentThread().getName() +"获取锁.....");
Thread.sleep(1000);
}catch(Exception e){

}finally{
System.out.println(Thread.currentThread().getName() +"释放锁.....");
lock.unlock();
}
}
}


class TestThread extends Thread{
@Override
public void run() {
new Main().test();
}
}


得到结果:
Thread-1获取锁.....
Thread-2获取锁.....
Thread-0获取锁.....
Thread-2释放锁.....
Thread-0释放锁.....
Thread-1释放锁.....


可见锁貌似没见效。下面我做个修改。
public class Main {


public static void main(String[] args) {

Lock lock = new ReentrantLock();
new TestThread(lock).start();
new TestThread(lock).start();
new TestThread(lock).start();
}
public  void test(Lock lock){


lock.lock();
try{
System.out.println(Thread.currentThread().getName() +"获取锁.....");
Thread.sleep(1000);
}catch(Exception e){

}finally{
System.out.println(Thread.currentThread().getName() +"释放锁.....");
lock.unlock();
}
}
}


class TestThread extends Thread{
Lock lock;

public TestThread(Lock lock) {
this.lock = lock;
}


@Override
public void run() {
new Main().test(lock);
}
}


执行结果:
Thread-0获取锁.....
Thread-0释放锁.....
Thread-1获取锁.....
Thread-1释放锁.....
Thread-2获取锁.....
Thread-2释放锁.....




可见生效了,其实很好理解。你要用同一把锁锁住才能满足需求。前者锁时成员变量,new的锁时对象私有的,每次new对象创建的是不同锁。




2)lockInterruptibly 函数 ,可以中断该线程


public class Main {

public static void main(String[] args) throws InterruptedException {

Lock lock = new ReentrantLock();
TestThread t1 = new TestThread(lock);
TestThread t2 = new TestThread(lock);
TestThread t3 = new TestThread(lock);

t1.start();t2.start();t3.start();

Thread.sleep(3000);
t2.interrupt();

}
public  void testInterruptibly(Lock lock) throws InterruptedException{


lock.lockInterruptibly();
try{
System.out.println(Thread.currentThread().getName() +"获取锁.....");
Thread.sleep(10000);
}finally{
System.out.println(Thread.currentThread().getName() +"释放锁.....");
lock.unlock();
}
}
}


class TestThread extends Thread{
Lock lock;

public TestThread(Lock lock) {
this.lock = lock;
}


@Override
public void run() {
try {
new Main().testInterruptibly(lock);
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()+"  被中断了....");
}
}
}




运行结果:
Thread-0获取锁.....
Thread-1  被中断了....
Thread-0释放锁.....
Thread-2获取锁.....
Thread-2释放锁.....




可见线程1的确被中止了。




3)tryLock 函数,尝试获取锁,返回boolean,立即返回
public class Main {

public static void main(String[] args) throws InterruptedException {

Lock lock = new ReentrantLock();
TestThread t1 = new TestThread(lock);
TestThread t2 = new TestThread(lock);
TestThread t3 = new TestThread(lock);

t1.start();t2.start();t3.start();

}


public  void test(Lock lock){


lock.lock();
try{
System.out.println(Thread.currentThread().getName() +"获取锁.....");
Thread.sleep(1000);
}catch(Exception e){

}finally{
System.out.println(Thread.currentThread().getName() +"释放锁.....");
lock.unlock();
}
}
}


class TestThread extends Thread{
Lock lock;

public TestThread(Lock lock) {
this.lock = lock;
}


@Override
public void run() {
if(lock.tryLock()){
try{
new Main().test(lock);
}finally{
lock.unlock();
}
}
}
}
执行结果:
Thread-0获取锁.....
Thread-0释放锁.....


结果发现,的确生效了,另外两个线程执行时,没有获取到锁,所以直接结束了。


下面我做个简单的修改,将tryLock换成另外的tryLock,接下来我们说说tryLock(long time, TimeUnit unit) throws InterruptedException;
修改后的代码如下:
public class Main {

public static void main(String[] args) throws InterruptedException {

Lock lock = new ReentrantLock();
TestThread t1 = new TestThread(lock);
TestThread t2 = new TestThread(lock);
TestThread t3 = new TestThread(lock);

t1.start();t2.start();t3.start();

}


public  void test(Lock lock){


lock.lock();
try{
System.out.println(Thread.currentThread().getName() +"获取锁.....");
Thread.sleep(1000);
}catch(Exception e){

}finally{
System.out.println(Thread.currentThread().getName() +"释放锁.....");
lock.unlock();
}
}
}


class TestThread extends Thread{
Lock lock;

public TestThread(Lock lock) {
this.lock = lock;
}


@Override
public void run() {
try {
if(lock.tryLock(10, TimeUnit.SECONDS)){
try{
new Main().test(lock);
}finally{
lock.unlock();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}




执行结果:
Thread-1获取锁.....
Thread-1释放锁.....
Thread-2获取锁.....
Thread-2释放锁.....
Thread-0获取锁.....
Thread-0释放锁.....


在获取锁的时候,等待了10秒,这个时间后,锁的确已经释放了。下面我将test()方法中等待的时间设置超过等待的时间10秒。
public class Main {

public static void main(String[] args) throws InterruptedException {

Lock lock = new ReentrantLock();
TestThread t1 = new TestThread(lock);
TestThread t2 = new TestThread(lock);
TestThread t3 = new TestThread(lock);

t1.start();t2.start();t3.start();

}


public  void test(Lock lock){


lock.lock();
try{
System.out.println(Thread.currentThread().getName() +"获取锁.....");
Thread.sleep(15000);
}catch(Exception e){

}finally{
System.out.println(Thread.currentThread().getName() +"释放锁.....");
lock.unlock();
}
}
}


class TestThread extends Thread{
Lock lock;

public TestThread(Lock lock) {
this.lock = lock;
}


@Override
public void run() {
try {
if(lock.tryLock(10, TimeUnit.SECONDS)){
try{
new Main().test(lock);
}finally{
lock.unlock();
}
}else{
System.out.println(Thread.currentThread().getName()+"   等待超时...");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
执行结果:
Thread-1获取锁.....
Thread-2   等待超时...
Thread-0   等待超时...
Thread-1释放锁.....




结果和预期的一致。


tryLock(...) 函数会尝试获取锁,如果拿不到锁,在没有设置等待时间的时候,会立即返回false。如果设置了等待时间,等待时间过去后,还是拿不到锁,会返回false,中端获取锁。




4) unlock() 函数,这个函数很简单,释放锁,只需要注意一个地方即可,代码必须放到finally中,确保不会因为程序异常导致死锁。


5) newCondition() 这个函数能实现object对象中的wait notify函数的功能。具体可以参考我同时写的另外一篇文章。

















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值