synchronized和lock

两者区别

  • synchronized是关键字,在发生异常的时候会自动占用释放线程占用的锁,不会发生死锁现象。
  • lock在发生异常时,如果没有主动通过unlock去释放锁,则很可能造成死锁现象。因此使用lock是需要在finally块释放对象锁。
  • lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断。
  • 通过lock可以知道有没有成功获得锁,而synchronized不能。
  • lock可以提高多个线程进行读操作的效率。

synchronized 是可以重入锁

原理是:当线程在获得锁之后,每一个锁会关联一个线程对象和计数器,当一个线程请求成功后,会记录下持有锁的线程,并且计数器+1,其他线程来获得锁时,需要等待。当前线程再来获得锁时,计数器会递增,线程退出同步代码块时,计数器会递减,计数器为0,则释放锁

/**
 *  synchronized 是可重入锁
 */
public class BMW extends Car {

	public synchronized void doSomething () throws Exception{
		System.out.println ("BWM:doSomething:" + Thread.currentThread ().getName ());
		carRun ();
	}
	
	public synchronized void  carRun () throws Exception{
		super.test ();
		System.out.println ("BWM:carRun:" + Thread.currentThread ().getName ());
	}
	
	public static void main ( String[] args )  throws Exception{
		BMW  bmw = new BMW ();
		bmw.doSomething ();
		
	}
	
}
class Car {
	public synchronized  void  test() throws Exception{
		Thread.sleep (5000);
		System.out.println ("car.test: "+Thread.currentThread ().getName ());
	}
}

这里的对象锁只有一个,就是 BMW 对象的锁,当执行 BMW .doSomething 时,该线程获得 BMW 对象的锁,在 doSomething 方法内执行 carRun 时再次请求BMW 对象的锁,因为synchronized 是重入锁,所以可以得到该锁,继续在 carRun 里执行父类的 test方法时第三次请求 BMW 对象的锁,同样可得到。

lock

lock接口提供4种锁的方法,而ReentrantLock 是lock接口的唯一实现类。

  • lock() :当前线程获得锁,其他线程只能等待,直到当前线程主动释放锁。
  • lockInterruptibly() : 获得可中断锁,线程A通过此方法获得锁时,线程B再来获得锁时,A已经获得锁,B只能等待,此时B可以调用interrupt ()来终止线程.
  • tryLock : 线程尝试去获得锁,如果获得到锁返回true,否则返回false。带时间参数的是如果没有获得错,等待多长时间再去尝试。

1、lock()

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.locks.ReentrantLock;

public class TestReenTrantLock {
	
	private static Logger logger = LoggerFactory.getLogger (TestReenTrantLock.class);
	
	public static void test () throws InterruptedException {
		
		logger.info ("{}: 执行了",Thread.currentThread ());
		
		Thread.sleep (5000);
		
		logger.info ("{}: 执行了完成",Thread.currentThread ());
		
	}
	
	public static void main ( String[] args ) {
		
		ReentrantLock  r = new ReentrantLock ();
		new Thread (){
			
			@Override
			public void  run (){
				
				
				logger.info ("{}: 开始",Thread.currentThread ());
				try {
					r.lock ();
					test ();
					r.lock ();
					logger.info ("{}: 又开始",Thread.currentThread ());
					test ();
					r.unlock ();
				} catch ( InterruptedException e ) {
					e.printStackTrace ();
				} finally {
					r.unlock ();
				}
				
			}
		
		}.start ();
		
		new Thread (){
			
			@Override
			public void  run (){
				logger.info ("{}: 开始",Thread.currentThread ());
				try {
					r.lock ();
					test ();
				} catch ( InterruptedException e ) {
					e.printStackTrace ();
				} finally {
					r.unlock ();
				}
				
			}
			
		}.start ();
	
	}
	
	
}

运行结果

[Thread-1] INFO floyd.learn.lock.TestReenTrantLock - Thread[Thread-1,5,main]: 开始
[Thread-1] INFO floyd.learn.lock.TestReenTrantLock - Thread[Thread-1,5,main]: 执行了
[Thread-0] INFO floyd.learn.lock.TestReenTrantLock - Thread[Thread-0,5,main]: 开始
[Thread-1] INFO floyd.learn.lock.TestReenTrantLock - Thread[Thread-1,5,main]: 执行了完成
[Thread-0] INFO floyd.learn.lock.TestReenTrantLock - Thread[Thread-0,5,main]: 执行了
[Thread-0] INFO floyd.learn.lock.TestReenTrantLock - Thread[Thread-0,5,main]: 执行了完成
[Thread-0] INFO floyd.learn.lock.TestReenTrantLock - Thread[Thread-0,5,main]: 又开始
[Thread-0] INFO floyd.learn.lock.TestReenTrantLock - Thread[Thread-0,5,main]: 执行了
[Thread-0] INFO floyd.learn.lock.TestReenTrantLock - Thread[Thread-0,5,main]: 执行了完成

2、lockInterruptibly()

public class LearnLock {
	
	private static Lock  lock = new ReentrantLock ();
	
	public  void  insert (Thread thread) throws InterruptedException {
		lock.lockInterruptibly ();
		try {
			System.out.println ( thread.getName ()+"获得了锁");
			long startTime = System.currentTimeMillis();
			
			for (; ; ) {
				if (System.currentTimeMillis() - startTime >= Integer.MAX_VALUE){
					break;
				}

			}
			System.out.println ("业务执行完");
		} catch ( Exception e ){
			e.printStackTrace ();
		} finally {
			lock.unlock ();
			System.out.println (thread.getName ()+"释放了锁");
		}
	}
	
	public static void main ( String[] args ) {
		LearnLock lock1 = new LearnLock ();
		LeThreadExtend test1 = new LeThreadExtend (lock1);
		LeThreadExtend  test2 = new LeThreadExtend (lock1);
		test1.start ();
		test2.start ();
		try {
			Thread.sleep (2000);
		} catch ( InterruptedException e ) {
			e.printStackTrace ();
		}
		//test2.interrupt() 可以注释掉执行一次,看看结果,对比一下
		test2.interrupt ();
		System.out.println ("执行完。。");
	}
}

3、tryLock

public class TestTryLock {
	
	private static ArrayList<Integer> arrayList = new ArrayList<Integer>();
	static         Lock               lock       = new ReentrantLock ();
	
	public static void main(String[] args) {
		new Thread(){
			@Override
			public void run(){
				Thread thread  = Thread.currentThread();
				boolean tryLock = false;
				try {
					tryLock = lock.tryLock(3, TimeUnit.SECONDS);
					System.out.println(thread.getName()+" "+tryLock);
					
					if (tryLock) {
						Thread.sleep (2000);
						System.out.println(thread.getName() + "拿到了锁");
						for(int i = 0;i<10;i++){
							arrayList.add(i);
						}
						lock.unlock();
						System.out.println(thread.getName()+"释放了锁");
					}
					
				} catch ( InterruptedException e ) {
					e.printStackTrace ();
				}
			}
		}.start();
		new Thread(){
			@Override
			public void run(){
				Thread thread  = Thread.currentThread();
				//boolean tryLock = lock.tryLock();
				boolean tryLock = false;
				try {
					tryLock = lock.tryLock(3, TimeUnit.SECONDS);
					System.out.println(thread.getName()+" "+tryLock);
					
					if (tryLock) {
						Thread.sleep (2000);
						System.out.println(thread.getName() + "拿到了锁");
						for(int i = 0;i<10;i++){
							arrayList.add(i);
						}
						lock.unlock();
						System.out.println(thread.getName()+"释放了锁");
					}
					
				} catch ( InterruptedException e ) {
					e.printStackTrace ();
				}
			}
		}.start();
	}
}

ReadWriteLock

ReadWriteLock 接口提供了读锁和写锁两个方法,ReentrantReadWriteLock是其实现类。多个线程可以同时申请读锁,但是在申请写锁时,需要等待所有的读锁全部释放后才可以申请成功。

public class TestReadWriteLock {
	
	public static void main ( String[] args ) {
		
		ReadWriteLock   rw = new ReentrantReadWriteLock ();
		TestReadWriteLock  test = new TestReadWriteLock ();
		
		new Thread (){
			@Override
			public void run(){
				test.read (rw,Thread.currentThread ());
				test.write (rw,Thread.currentThread ());
			}
		}.start ();
		new Thread (){
			@Override
			public void run(){
				test.read (rw,Thread.currentThread ());
				test.write (rw,Thread.currentThread ());
			}
		}.start ();
		
		
	}

	
	public void  read (ReadWriteLock  rw,Thread  thread){
		try {
			rw.readLock ().lock ();
			System.out.println (thread.getName ()+"> 开始读取"+System.currentTimeMillis ());
			Thread.sleep (2000);
			System.out.println (thread.getName ()+"> 读取结束"+System.currentTimeMillis ());
			
		} catch ( Exception  e) {
			e.printStackTrace ();
		} finally {
			rw.readLock ().unlock ();
			System.out.println (thread.getName ()+"> 读取锁释放了"+System.currentTimeMillis ());
		}
	}
	
	public void write(ReadWriteLock rw,Thread thread){
		try {
			rw.writeLock ().lock ();
			System.out.println (thread.getName ()+"> 开始写入");
			Thread.sleep (5000);
			System.out.println (thread.getName ()+"> 写入结束");
			
		} catch ( Exception e ) {
			e.printStackTrace ();
		} finally {
			rw.writeLock ().unlock ();
			System.out.println (thread.getName ()+"> 写入锁释放了");
		}
	}
}

参考
https://www.cnblogs.com/incognitor/p/9894604.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值