Lock锁和synchronized锁的实现以及其他几个问题

上一篇博客写了几种锁,但是没写完,具体的实现没有验证,今天来解决它。

首先Lock和Synchronized的区别:

1.Lock默认是公平锁,谁等待的时间长谁优先获得锁,Synchronized为非公平锁遵循抢占式调度。

2.Lock锁被获得时,有线程在等待可以先中断等待,然后执行其他方法,而Synchronized锁的等待线程则会一直等待着。

3.Lock是用Java写的接口,里面有很多api方法,可以判断锁是否被占用,而Synchronized是多线程的内置关键字,不能判断锁是否被占用。

4.Synchronized锁在执行完了之后会自动释放锁,而Lock则必须手动释放(调用unLock()方法)

其实Synchronized我们都应该很熟悉了,重量型锁在上一篇博客中写了它的生产者和消费者的例子,这里就不在多说。下面来看Lock的例子:

public class locktest implements Runnable{

	
	
	@Override
	public void run() {
		say();
		
	}

	
	public void say() {
		Lock lock=new ReentrantLock();
		lock.lock();//加上锁了
		for (int i = 0; i < 10000; i++) {
			System.out.println(Thread.currentThread().getName()+":"+i);
		}
		try {
			
		}finally {
			lock.unlock();//释放锁
		}
	}
	
}
//这是线程

这个代码是错的,因为这里的锁的创建是放在方法里面的,这样的话每次使用此目标对象创建一个线程,就会执行一次方法,那么就会重新创建一个锁,每次获得的锁都是新的,也就不存在锁之间的竞争了,这个案例也可以解释在类中如果有俩个Synchronized方法,那么当A线程执行一个时,B线程能不能再执行另一个方法的问题。(之后会有案例)

正确的代码如下:

public class locktest implements Runnable{

	
	Lock lock=new ReentrantLock();
	@Override
	public void run() {
		say();
		
	}

	
	public void say() {
		
		lock.lock();//加上锁了
		for (int i = 0; i < 10000; i++) {
			System.out.println(Thread.currentThread().getName()+":"+i);
		}
		try {
			
		}finally {
			lock.unlock();//释放锁
		}
	}
	
}


主方法:

public static void main(String[] args) {
		locktest lt=new locktest();
		Thread td1=new Thread(lt);
		Thread td2=new Thread(lt);
		td1.start();
		td2.start();
	}

这就是Lock锁

那么在深入的看看,java.util.concurrent这个包下有哪些锁接口和具体的实现类。

首先第一个就是Lock接口了,上面有演示,直接看API方法:

  • void lock() – 如果锁可用就获得锁,如果锁不可用就阻塞直到锁释放

  • void lockInterruptibly() – 和 lock()方法相似, 但阻塞的线程可中断,抛出 java.lang.InterruptedException异常

  • boolean tryLock() –lock() 方法的非阻塞版本;尝试获取锁,如果成功返回true

  • boolean tryLock(long timeout, TimeUnit timeUnit) – 和tryLock()方法相似,只是 在放弃尝试获取锁之前等待指定的时间。

  • void unlock() – 释放锁

实现Lock接口的是ReentrantLock ,实例就是上面的。

第二个接口是读写锁接口:ReadWriteLock ,ReentrantReadWriteLock 类实现了此接口。这个锁可以拆分为俩个锁,分别是读锁和写锁。调用相应的API方法就可以得到;

writeLock()  获得写锁

readLock()  获得读锁

读-读不互斥

读-写互斥

写-写互斥

Lock暂时就总结到这,因为用的少,所以知道了思想之后,用的时候在看就行。

接下来要试验一下这个问题。

一个类中有俩个Syncronized方法那么当一个执行时另一个会不会执行?

看了资料有的人说会有的说不会,经过自己的验证发现不会执行

代码如下:

public class Orange {

	public synchronized void chi() {
		System.out.println("吃橙子了");
	}
	
	public synchronized void mai() {
		System.out.println("买橙子了");
	}
	
}


public class OrangeThread1 implements Runnable{

	private Orange orange;
	public OrangeThread1(Orange orange) {
		this.orange=orange;
	}
	
	@Override
	public void run() {
		try {
			Thread.sleep(10000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		for (int i = 0; i < 100; i++) {
			orange.chi();
		}
		
	}

	
	
}


public class OrangeThread2 implements Runnable{

	private Orange orange;
	public OrangeThread2(Orange orange) {
		this.orange=orange;
	}
	
	@Override
	public void run() {
		for (int i = 0; i < 100; i++) {
			orange.mai();
		}
		
	}

	
}


public static void main(String[] args) {
		Orange orange=new Orange();
		Thread thread1=new Thread(new OrangeThread1(orange));
		Thread thread2=new Thread(new OrangeThread2(orange));
		thread1.start();
		thread2.start();
	}

道理很简单,当方法chi执行时对象锁已经被一个线程拿走了,当方法mai在执行时,他的对象锁还是Orange,而此对象锁已经被之前的线程占用了,所以当然要等待了。

参考博客:https://blog.csdn.net/sinat_26279177/article/details/80646301

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值