从零开始java多线程到分布式锁(十一):Lock的基本概念

一:java中的锁

    java中的锁关键字分为3种:Lock、Synchronized以及volatile。

1 .Lock和Synchronized区别

    Lock: 为java中的显示锁,锁的获取和释放可以在不同的

   Synchronized:为java中隐石锁,所得获取和释放是在同步代码块的开始结束位置,是java实现同步的最简单的方法。

 

2.Synchronized和volatile的区别

 Synchronized:是java提供一个重量级别的锁,可以保证可见性、原子性等。

 volatile:是java5之后对于Synchronized优化的轻锁,可以保证多线程锁的可见性,但是原子性无法保证。

3.为什么不用Synchronized(valatitle)而采用Lock

 在上面几节我们谈到了Synchronized/volatitle的使用优化,尽然如此为什么还要用Lock呢?原因就是:前2种锁的加锁/解锁过程是针对读和写的。也就是如果一个方法既有读和写,其中读的频率有99%而写只有1%,Synchronized会将方法加锁导致99%读也会被加锁,而我们读操作是没有改变任何东西,只要读就行。因此Lock是为了消除Synchronized的读操作的加锁/解锁过程的。

二:Lock锁也是一个对象锁

  注意Lock也是一个对象锁,这就是说,一个对象一旦拥有多个加锁的方法,他也是同步执行的,代码如下:

1.没有锁的

package Lock;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 验证Lock也是一个对象锁
 * @author monxz
 *
 */
public class ObjectLock {
	/**
	 * 定义Lock
	 */
 private Lock  lock=new ReentrantLock();
 
 public void  methodA() {
	 //加锁
//	 lock.lock();	 
	 try {
		 System.out.println("=====A方法开始执行");
		 for(int i =  0; i < 3 ;i ++){
			 System.out.println("=====线程执行方法A:"+Thread.currentThread().getName()+",顺序:"+i);
			 Thread.sleep(1000);
		 }
		 System.out.println("=====A方法执行结束");
	} catch (Exception e) {
		e.printStackTrace();
	}finally {
		//解锁
//		lock.unlock();
	}	 
 }
 
 public void  methodB() {
	 //加锁
//	 lock.lock();	 
	 try {
		 System.out.println("=====B方法开始执行");
		 for(int i =  0; i < 3 ;i ++){
			 System.out.println("=====线程执行方法B:"+Thread.currentThread().getName()+",顺序:"+i);
			 Thread.sleep(1000);
		 }
		 System.out.println("=====B方法执行结束");
	} catch (Exception e) {
		e.printStackTrace();
	}finally {
		//解锁
//		lock.unlock();
	}	 
 }
 
 public static void main(String[] args) {
	 
	/**
	 * ta,tb线程执行A,B俩个方法,注意这里ta,tb是同时执行的
	 */
	ObjectLock  lockService = new ObjectLock();
	ThreadA  ta =new ThreadA(lockService);
	ta.setName("ta");
	ta.start();	
	ThreadB tb =new ThreadB(lockService);
	tb.setName("tb");
	tb.start();
}
 
 
 
 
 
}
 
 //定义线程A类
 class ThreadA  extends Thread{
	 private ObjectLock  lockService;
	 public ThreadA(ObjectLock  ls){
		 this.lockService = ls;
	 }
	 @Override
	    public void run() {
		 lockService.methodA();
	    }
 }
 
 //定义线程B类
 class ThreadB  extends Thread{
	 private ObjectLock  lockService;
	 public ThreadB(ObjectLock  ls){
		 this.lockService = ls;
	 }
	 @Override
	    public void run() {
		 lockService.methodB();
	    }
 }


运行结果:注意A,B是同事执行的,没有顺序

2.使用Lock锁

这里只要把上面的A,B方法中的lock.lock()和lock.unlock()注释即是A,B都加锁了。

运行结果:结果与上面比对就很明显了吧。

 

 

三:Lock锁的API

1.首先这里先截图出api

 

2.无锁多线程运行

 在无锁的情况下,多线程运行或出现没有顺序,这里上代码:

/**
 * 无锁多线程演示
 * @author monxz
 *
 */
class  NoLockTest  implements  Runnable{
	@Override
	public void run() {
		 for (int i = 0; i < 5; i++) {
	            
	            try {
	            	System.out.println(Thread.currentThread().getName() + "线程:执行顺序: "+i);
	                Thread.sleep(1000);
	            } catch (InterruptedException e) {
	                e.printStackTrace();
	            }
	        }	
	}	
}


	 public static void main(String[] args) {
		NoLockTest   test =new NoLockTest();


		for(int i = 0; i < 5 ; i++){
			Thread  thread  =  new Thread(test, "线程"+i);
			thread.start();
		}
	}

运行结果:

                                                                    

3.简单的Lock锁 

/**
 * 简单的lock演示
 * 说明:当前线程获取锁并且在执行方法,其他线程同时也获取锁,获取不到其他线程进入阻塞队列
 * @author monxz
 *
 */
class  onlysimpleLockTest implements  Runnable{
	Lock  lock  = new ReentrantLock();
	
	@Override
	public void run() {
		try {
			//加锁
			lock.lock();
			 for (int i = 0; i < 5; i++) {
				System.out.println(Thread.currentThread().getName() + "线程:执行顺序: "+i);
	            Thread.sleep(1000);
			 }		
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			//释放锁
			lock.unlock();
		}
		
	}	
}

	 public static void main(String[] args) {
		
		onlysimpleLockTest   test =new onlysimpleLockTest();

		for(int i = 0; i < 5 ; i++){
			Thread  thread  =  new Thread(test, "线程"+i);
			thread.start();
		}
	}

运行结果(部分):

4.简单的tryLock()

/**
 * 简单的tryLock()演示
 * 说明:如果当前线程获取到锁并且执行中,那么其他线程获取不到锁,其他线程死亡
 * @author monxz
 *
 */
 class  tryLockTest implements  Runnable{
	Lock  lock  = new ReentrantLock();
	 @Override
	public void run() {
		if(lock.tryLock()){			            	            	
            try {
            	for (int i = 0; i < 5; i++) {
            	System.out.println(Thread.currentThread().getName() + "线程:执行顺序: "+i);
                Thread.sleep(1000);
            	}
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
            	lock.unlock();
            }	                       

		}else{
			System.out.println("线程"+Thread.currentThread().getName()+"没有获取锁!");
		}		
	}	 
 }

	 public static void main(String[] args) {		
		tryLockTest   test =new tryLockTest();
		for(int i = 0; i < 5 ; i++){
			Thread  thread  =  new Thread(test, "线程"+i);
			thread.start();
		}
	}

 运行结果:

5.tryLock(Long  time  timeUtil timeUtil) 

 /**
  * tryLock(time,timePS)添加时间等待
  * 说明:多线程中随机一个线程获取当前锁, 如果在当前线程在等待时间结束前没有执行完毕,其他线程全部放弃。如果执行完毕,剩余线程共同执行tryLock();
  * 示例:比如100个线程,第1个线程获取锁执行代码在等待时间结束前没有执行完成,其他99个线程放弃死亡。如果执行完毕,剩余的99个随机一个执行,其他98个死亡
  * @author monxz
  *
  */
 class  tryLockTimeTest implements  Runnable{
	Lock  lock  = new ReentrantLock();
	 @Override
	public void run() {
		 try {
			 if(lock.tryLock(1000,TimeUnit.MILLISECONDS)){			            	            			            
            	for (int i = 0; i < 5; i++) {
            	System.out.println(Thread.currentThread().getName() + "线程:执行顺序: "+i);
                Thread.sleep(1000);
            	}
           
            	 lock.unlock();
		            	                       

				}else{
					System.out.println("线程"+Thread.currentThread().getName()+"没有获取锁!");
				}
		} catch (Exception e) {
			e.printStackTrace();
		}				
	}
	 
 }
	 public static void main(String[] args) {

		 tryLockTimeTest   test =new tryLockTimeTest();
		for(int i = 0; i < 5 ; i++){
			Thread  thread  =  new Thread(test, "线程"+i);
			thread.start();
		}
	}
	
}

运行结果:

 

四:Lock的其他的一些api

getHoldCount() :获取当前锁定(got)的个数 

getQueueLength() :获取当前正在等待获取(getting)锁的线程数(Threads)

getWaitQueueLength(Condition) :返回等待(await)与此锁定(got)的Condition相关的个数

源码: https://gitee.com/monxz/lock_of_java.git

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值