`
uule
  • 浏览: 6304881 次
  • 性别: Icon_minigender_1
  • 来自: 一片神奇的土地
社区版块
存档分类
最新评论

ReentrantLock与synchronized

 
阅读更多

关于互斥锁:

所谓互斥锁, 指的是一次最多只能有一个线程持有的锁. 在jdk1.5之前, 我们通常使用synchronized机制控制多个线程对共享资源的访问. 而现在, Lock提供了比synchronized机制更广泛的锁定操作, Lock和synchronized机制的主要区别:

synchronized机制提供了对与每个对象相关的隐式监视器锁的访问, 并强制所有锁获取和释放均要出现在一个块结构中, 当获取了多个锁时, 它们必须以相反的顺序释放. synchronized机制对锁的释放是隐式的, 只要线程运行的代码超出了synchronized语句块范围, 锁就会被释放. 而Lock机制必须显式的调用Lock对象的unlock()方法才能释放锁, 这为获取锁和释放锁不出现在同一个块结构中, 以及以更自由的顺序释放锁提供了可能. 

 

 

关于可重入: 

一、2.4.1 内部锁

Java 提供了原子性的内置锁机制: sychronized 块。它包含两个部分:锁对象的引用和这个锁保护的代码块:

synchronized(lock) {

// 访问或修改被锁保护的共享状态

}

内部锁扮演了互斥锁( mutual exclusion lock, 也称作 mutex )的角色,一个线程拥有锁的时候,别的线程阻塞等待。

 

2.4.2 重进入(Reentrancy )

重入性:指的是同一个线程多次试图获取它所占有的锁,请求会成功。当释放锁的时候,直到重入次数清零,锁才释放完毕。

Public class Widget {

      Public synchronized void doSomething(){

           …

      }

}

Public class LoggingWidget extends Widget {

   Public synchronized void doSomething(){

      System.out.println(toString()+”:calling doSomething”);

      Super.doSomething();

   }

}

 

二、一般来说,在多线程程序中,某个任务在持有某对象的锁后才能运行任务,其他任务只有在该任务释放同一对象锁后才能拥有对象锁,然后执行任务。于是,想到,同一个任务在持有同一个对象的锁后,在不释放锁的情况下,继续调用同一个对象的其他同步(synchronized)方法,该任务是否会再次持有该对象锁呢? 

    答案是肯定的。同一个任务在调用同一个对象上的其他synchronized方法,可以再次获得该对象锁。 

 

synchronized  m1(){
//加入此时对锁a的计数是N
 m2();  //进入m2的方法体之后锁计数是N+1,离开m2后是N
}
synchronized m2(){}

 同一任务和对象锁的问题:http://www.iteye.com/topic/728485

 

 

 

/*public class ReentrantLock 
extends Object implements Lock, Serializable
*/

  

一个可重入的互斥锁 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大。

 

ReentrantLock 将由最近成功获得锁,并且还没有释放该锁的线程所拥有。当锁没有被另一个线程所拥有时,调用 lock 的线程将成功获取该锁并返回。如果当前线程已经拥有该锁,此方法将立即返回。可以使用 isHeldByCurrentThread() 和 getHoldCount() 方法来检查此情况是否发生。

 

此类的构造方法接受一个可选的公平 参数。当设置为 true 时,在多个线程的争用下,这些锁倾向于将访问权授予等待时间最长的线程。否则此锁将无法保证任何特定访问顺序。与采用默认设置(使用不公平锁)相比,使用公平锁的程序在许多线程访问时表现为很低的总体吞吐量(即速度很慢,常常极其慢),但是在获得锁和保证锁分配的均衡性时差异较小。不过要注意的是,公平锁不能保证线程调度的公平性。因此,使用公平锁的众多线程中的一员可能获得多倍的成功机会,这种情况发生在其他活动线程没有被处理并且目前并未持有锁时。还要注意的是,未定时的 tryLock 方法并没有使用公平设置。因为即使其他线程正在等待,只要该锁是可用的,此方法就可以获得成功。

JDK:http://www.xasxt.com/java/api/java/util/concurrent/locks/ReentrantLock.html

 

 

/*构造方法摘要
ReentrantLock() 
          创建一个 ReentrantLock 的实例。
ReentrantLock(boolean fair) 
          创建一个具有给定公平策略的 ReentrantLock。
*/

  

/**public void lock()
获取锁。
如果该锁没有被另一个线程保持,则获取该锁并立即返回,将锁的保持计数设置为 1。
如果当前线程已经保持该锁,则将保持计数加 1,并且该方法立即返回。
如果该锁被另一个线程保持,则出于线程调度的目的,禁用当前线程,并且在获得锁之前,该线程将一直处于休眠状态,此时锁保持计数被设置为 1。
*/

  

ReentrantLock 的lock机制有2种,忽略中断锁和响应中断锁,这给我们带来了很大的灵活性。比如:如果A、B 2个线程去竞争锁,A线程得到了锁,B线程等待,但是A线程这个时候实在有太多事情要处理,就是 一直不返回,B线程可能就会等不及了,想中断自己,不再等待这个锁了,转而处理其他事情。这个时候ReentrantLock就提供了2种机制,第一,B线程中断自己(或者别的线程中断它),但是ReentrantLock 不去响应,继续让B线程等待,你再怎么中断,我全当耳边风(synchronized原语就是如此);第二,B线程中断自己(或者别的线程中断它),ReentrantLock 处理了这个中断,并且不再等待这个锁的到来,完全放弃。请看例子:

Example1:

 

package test;

public interface IBuffer {
	public void write();
    public void read() throws InterruptedException;
}

使用Synchronized:

package test;

public class Buffer implements IBuffer {

	private Object lock;

    public Buffer() {
        lock = this;
    }

    public void write() {
        synchronized (lock) {
            long startTime = System.currentTimeMillis();
            System.out.println("开始往这个buff写入数据…");
            for (;;)// 模拟要处理很长时间
            {
                if (System.currentTimeMillis() - startTime > Integer.MAX_VALUE)
                    break;
            }
            System.out.println("终于写完了");
        }
    }

    public void read() {
        synchronized (lock) {
            System.out.println("从这个buff读数据");
        }
    }

}

   使用ReentrantLock:

package test;
import java.util.concurrent.locks.ReentrantLock;
public class BufferInterruptibly implements IBuffer {

	private ReentrantLock lock = new ReentrantLock();

    public void write() {
        lock.lock();
        try {
            long startTime = System.currentTimeMillis();
            System.out.println("开始往这个buff写入数据…");
            for (;;)// 模拟要处理很长时间
            {
                if (System.currentTimeMillis() - startTime > Integer.MAX_VALUE)
                    break;
            }
            System.out.println("终于写完了");
        } finally {
            lock.unlock();
        }
    }

    public void read() throws InterruptedException{
        lock.lockInterruptibly();// 注意这里,可以响应中断
        try {
            System.out.println("从这个buff读数据");
        } finally {
            lock.unlock();
        }
    }

}

  

测试类(注意那两个线程不是内部类!):

package test;

public class Test {
	 //是用ReentrantLock,还是用synchronized
    public static boolean useSynchronized = false;
    public static void main(String[] args) {
        IBuffer buff = null;
        if(useSynchronized){
            buff = new Buffer();
        }else{
            buff = new BufferInterruptibly();    
        }
        final Writer writer = new Writer(buff);
        final Reader reader = new Reader(buff);
        writer.start();
        reader.start();
        new Thread(new Runnable() {
            public void run() {
                long start = System.currentTimeMillis();
                for (;;) {
                    // 等5秒钟去中断读
                    if (System.currentTimeMillis() - start > 5000) {
                        System.out.println("不等了,尝试中断");
                        reader.interrupt();
                        break;
                    }

                }

            }
        }).start();
    }    
}

	class Writer extends Thread {	
	    private IBuffer buff;
	
	    public Writer(IBuffer buff) {
	        this.buff = buff;
	    }
	
	    @Override
	    public void run() {
	        buff.write();
	    }
	}
	
	class Reader extends Thread {
	    private IBuffer buff;
	    public Reader(IBuffer buff) {
	        this.buff = buff;
	    }
	    @Override
	    public void run() {
	        try {
	            buff.read();
	        } catch (InterruptedException e) {
	            System.out.println("我不读了");   
	        }
	        System.out.println("读结束");
	    }
	}

 结果:

使用ReentrantLock时:

开始往这个buff写入数据…

不等了,尝试中断

我不读了

读结束

 

使用Synchronized时:

开始往这个buff写入数据…

不等了,尝试中断

实例来源:http://blog.csdn.net/quqi99/article/details/5298017

 

 

实例2:

http://junlas.iteye.com/blog/846460

实例3:

http://www.blogjava.net/killme2008/archive/2007/09/14/145195.html

 

 

重要:

一个证明可中断的例子:http://yanxuxin.iteye.com/blog/566713

关于多线程问题,signalAll,await问题:http://www.iteye.com/problems/72378

ReentrantLock :http://hujin.iteye.com/blog/479689

 

java的concurrent用法详解:

http://www.open-open.com/bbs/view/1320131360999

 

ReentrantLock-互斥同步器:

http://www.cnblogs.com/mandela/archive/2011/04/08/2009810.html

 

一个重要Example:

 

package tags;

import java.util.Calendar;

public class TestLock {
	private ReentrantLock lock = null;
	
	public int data = 100;     // 用于线程同步访问的共享数据

	public TestLock() {
		lock = new ReentrantLock(); // 创建一个自由竞争的可重入锁
	}
	public ReentrantLock getLock() {
		return lock;
	}
	
	public void testReentry() {
		lock.lock();
		Calendar now = Calendar.getInstance();
		System.out.println(now.getTime() + " " + Thread.currentThread()	+ " get lock.");
	}

	public static void main(String[] args) {
		TestLock tester = new TestLock();

		//1、测试可重入
		tester.testReentry();
		tester.testReentry(); // 能执行到这里而不阻塞,表示锁可重入
		tester.testReentry(); // 再次重入

		// 释放重入测试的锁,要按重入的数量解锁,否则其他线程无法获取该锁。
		tester.getLock().unlock();
		tester.getLock().unlock();
		tester.getLock().unlock();

		//2、测试互斥
		// 启动3个线程测试在锁保护下的共享数据data的访问
		new Thread(new workerThread(tester)).start();
		new Thread(new workerThread(tester)).start();
		new Thread(new workerThread(tester)).start();
	}


	// 线程调用的方法
	public void testRun() throws Exception {
		lock.lock();

		Calendar now = Calendar.getInstance();
		try {
			// 获取锁后显示 当前时间 当前调用线程 共享数据的值(并使共享数据 + 1)
			System.out.println(now.getTime() + " " + Thread.currentThread()+ " accesses the data " + data++);
			Thread.sleep(1000);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
}

// 工作线程,调用TestServer.testRun
class workerThread implements Runnable {

	private TestLock tester = null;

	public workerThread(TestLock testLock) {
		this.tester = testLock;
	}

	public void run() {
		try {
			tester.testRun();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

Example3:

 

package tags;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockSample {

	public static void main(String[] args) {
		testSynchronized();
		//testReentrantLock();
	}

	public static void testReentrantLock() {
		final SampleSupport1 support = new SampleSupport1();
		Thread first = new Thread(new Runnable() {
			public void run() {
				try {
					support.doSomething();
				}
				catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		});

		Thread second = new Thread(new Runnable() {
			public void run() {
				try {
					support.doSomething();
				}
				catch (InterruptedException e) {
					System.out.println("Second Thread Interrupted without executing counter++,beacuse it waits a long time.");
				}
			}
		});

		executeTest(first, second);
	}

	public static void testSynchronized() {
		final SampleSupport2 support2 = new SampleSupport2();

		Runnable runnable = new Runnable() {
			public void run() {
				support2.doSomething();
			}
		};

		Thread third = new Thread(runnable);
		Thread fourth = new Thread(runnable);

		executeTest(third, fourth);
	}

	/**
	 * Make thread a run faster than thread b,
     * then thread b will be interruted after about 1s.
	 * @param a
	 * @param b
	 */
	public static void executeTest(Thread a, Thread b) {
		a.start();
		try {
			Thread.sleep(100);
			b.start(); // The main thread sleep 100ms, and then start the second thread.

			Thread.sleep(1000);
    // 1s later, the main thread decided not to allow the second thread wait any longer.
			b.interrupt(); 
		}
		catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

abstract class SampleSupport {

	protected int counter;

	/**
	 * A simple countdown,it will stop after about 5s. 
	 */
	public void startTheCountdown() {
		long currentTime = System.currentTimeMillis();
		for (;;) {
			long diff = System.currentTimeMillis() - currentTime;
			if (diff > 5000) {
				break;
			}
		}
	}
}

class SampleSupport1 extends SampleSupport {

	private final ReentrantLock lock = new ReentrantLock();

	public void doSomething() throws InterruptedException {
		lock.lockInterruptibly(); // (1)
		System.out.println(Thread.currentThread().getName() + " will execute counter++.");
		startTheCountdown();
		try {
			counter++;
		}
		finally {
			lock.unlock();
		}
	}
}

class SampleSupport2 extends SampleSupport {

	public synchronized void doSomething() {
		System.out.println(Thread.currentThread().getName() + " will execute counter++.");
		startTheCountdown();
		counter++;
	}
}

 在这个例子中,辅助类SampleSupport提供一个倒计时的功能startTheCountdown(),这里倒计时5s左右。SampleSupport1,SampleSupport2继承其并分别的具有doSomething()方法,任何进入方法的线程会运行5s左右之后counter++然后离开方法释放锁。SampleSupport1是使用ReentrantLock机制,SampleSupport2是使用synchronized机制。 


    testSynchronized()和testReentrantLock()都分别开启两个线程执行测试方法executeTest(),这个方法会让一个线程先启动,另一个过100ms左右启动,并且隔1s左右试图中断后者。结果正如之前提到的第二点:interrupt()对于synchronized是没有作用的,它依然会等待5s左右获得锁执行counter++;而ReentrantLock机制可以保证在线程还未获得并且试图获得锁时如果发现线程中断,则抛出异常清除中断标记退出竞争。所以testReentrantLock()中second线程不会继续去竞争锁,执行异常内的打印语句后线程运行结束。 

来源:http://yanxuxin.iteye.com/blog/566713

 

Example4:

三个线程,线程名分别为A、B、C,设计程序使得三个线程循环打印“ABC”10次后终止。如:ABCABCABCABCABCABCABCABCABCABC

 

package tags;

import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockPractice {

	static ReentrantLock lock = new ReentrantLock();
	private static String[] threadArr = {"A","B","C"};
	
	public static void main(String[] args){
		ReentrantLockPractice pc = new ReentrantLockPractice();
		pc.startDemo();
	}
	
	void startDemo(){
		for(int i = 0;i<10;i++){
			for(String name : threadArr){
				TestThread t = new TestThread(name);
				t.start();
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
	

	class TestThread extends Thread{
		
		//自定义线程名字
		TestThread(String str){
			super(str);			
		}
		
		public void run(){
			try {
				lock.lockInterruptibly();
				System.out.print(Thread.currentThread().getName());
			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally{
				lock.unlock();
			}	
		}
	}
	
}

 注意与Example2的区别,一个线材类定义在内部,一个在外部,注意区别。

 其他方法:

http://hxraid.iteye.com/blog/607228

 

 

 

 

 

相同:ReentrantLock提供了synchronized类似的功能和内存语义。

 

不同:

1.ReentrantLock功能性方面更全面,比如时间锁等候,可中断锁等候,锁投票等,因此更有扩展性。在多个条件变量和高度竞争锁的地方,用ReentrantLock更合适,ReentrantLock还提供了Condition,对线程的等待和唤醒等操作更加灵活,一个ReentrantLock可以有多个Condition实例,所以更有扩展性。

2.ReentrantLock必须在finally中释放锁,否则后果很严重,编码角度来说使用synchronized更加简单,不容易遗漏或者出错。

3.ReentrantLock 的性能比synchronized会好点。

4.ReentrantLock提供了可轮询的锁请求,他可以尝试的去取得锁,如果取得成功则继续处理,取得不成功,可以等下次运行的时候处理,所以不容易产生死锁,而synchronized则一旦进入锁请求要么成功,要么一直阻塞,所以更容易产生死锁。

 

1、Lock的某些方法可以决定多长时间内尝试获取锁,如果获取不到就抛异常,这样就可以一定程度上减轻死锁的可能性。

如果锁被另一个线程占据了,synchronized只会一直等待,很容易错序死锁 

2、synchronized的话,锁的范围是整个方法或synchronized块部分;而Lock因为是方法调用,可以跨方法,灵活性更大 

3、便于测试,单元测试时,可以模拟Lock,确定是否获得了锁,而synchronized就没办法了

 

 

ReentrantLock比synchronized 强大在哪儿?

简单说: 

1、ReentrantLock可以实现fair lock 

 

public ReentrantLock(boolean fair) {   

    sync = (fair)? new FairSync() : new NonfairSync();  

}  

所谓fair lock就是看获得锁的顺序是不是和申请锁的时间的顺序是一致的 

 

2、ReentrantLock支持中断处理 

 

public final void acquireInterruptibly(int arg) throws InterruptedException {  

    if (Thread.interrupted())  

        throw new InterruptedException();  

    if (!tryAcquire(arg))  

        doAcquireInterruptibly(arg);  

}  

就是说那些持有锁的线程一直不释放,正在等待的线程可以放弃等待。 

 

3、ReentrantLock可以和condition结合使用 

 

public boolean hasWaiters(Condition condition) {  

    if (condition == null)  

        throw new NullPointerException();  

    if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))  

        throw new IllegalArgumentException("not owner");  

    return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);  

}  

 

public int getWaitQueueLength(Condition condition) {  

    if (condition == null)  

        throw new NullPointerException();  

    if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))  

        throw new IllegalArgumentException("not owner");  

    return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);  

}  

 

内置锁synchronized

显式锁Lock

ReentrantLock代码剖析之ReentrantLock.lock

ReentrantLock中tryLock的使用问题(注意循环)

 

 

synchronized是可重入锁

如果一个获取锁的线程调用其它的synchronized修饰的方法,会发生什么?

 

从设计上讲,当一个线程请求一个由其他线程持有的对象锁时,该线程会阻塞。当线程请求自己持有的对象锁时,如果该线程是重入锁,请求就会成功,否则阻塞。

 

我们回来看synchronized,synchronized拥有强制原子性的内部锁机制,是一个可重入锁。因此,在一个线程使用synchronized方法时调用该对象另一个synchronized方法,即一个线程得到一个对象锁后再次请求该对象锁,是永远可以拿到锁的。

 

在Java内部,同一个线程调用自己类中其他synchronized方法/块时不会阻碍该线程的执行,同一个线程对同一个对象锁是可重入的,同一个线程可以获取同一把锁多次,也就是可以多次重入。原因是Java中线程获得对象锁的操作是以线程为单位的,而不是以调用为单位的。

 

synchronized可重入锁的实现

 

每个锁关联一个线程持有者和一个计数器。当计数器为0时表示该锁没有被任何线程持有,那么任何线程都都可能获得该锁而调用相应方法。当一个线程请求成功后,JVM会记下持有锁的线程,并将计数器计为1。此时其他线程请求该锁,则必须等待。而该持有锁的线程如果再次请求这个锁,就可以再次拿到这个锁,同时计数器会递增。当线程退出一个synchronized方法/块时,计数器会递减,如果计数器为0则释放该锁。

  • TestLock.rar (1019 Bytes)
  • 描述: 助于理解的例子
  • 下载次数: 53
分享到:
评论
5 楼 970655147 2015-12-25  
xiaoxi0324 写道
--ReentrantLock 的lock机制有2种,忽略中断锁和响应中断锁,这给我们带来了很大的灵活性

如上:这个特性lock API 有说支持吗?
示例代码使用的是Thread自身的API,难道在synchronized下 实现不了?
Thread处于wait状态,中断会抛异常,synchronized模式时也一样catch这个异常。
严谨一点,删除掉非API上说明的部分。


。。楼主将自己的想法分享出来而已, 要严谨的话, 看官方文档吧
4 楼 xiaoxi0324 2014-10-31  
--ReentrantLock 的lock机制有2种,忽略中断锁和响应中断锁,这给我们带来了很大的灵活性

如上:这个特性lock API 有说支持吗?
示例代码使用的是Thread自身的API,难道在synchronized下 实现不了?
Thread处于wait状态,中断会抛异常,synchronized模式时也一样catch这个异常。
严谨一点,删除掉非API上说明的部分。
3 楼 a_lee 2013-04-19  
整理得很好
2 楼 blackproof 2013-01-10  
讲得挺好滴,要是再说说怎么实现的就更好了
1 楼 medicine 2012-08-29  
  整理的真好

相关推荐

    ReentrantLock与synchronized区别

    java语言 并发编程 ReentrantLock与synchronized区别 详解

    ReentrantLock 与 synchronized 简介

    java lock synchronized

    java ReentrantLock详解.docx

    ReentrantLock与synchronized来的区别 1.synchronized是独占锁,加锁和解锁的过程自动进行,易于操作,但不够灵活。ReentrantLock也是独占锁,加锁和解锁的过程需要手动进行,不易操作,但非常灵活。 2.synchronized...

    深入java并发编程,使用ReentrantLock和 Synchronized加锁

    深入java并发编程,使用ReentrantLock和 Synchronized加锁

    Java中的ReentrantLock类最全讲义

    目录: 简介 ReentrantLock的基本用法 2.1 创建ReentrantLock 2.2 获取锁和释放锁 公平性与非公平性 3.1 公平锁 3.2 非公平锁 中断响应 ...ReentrantLock与synchronized的对比 最佳实践与注意事项

    Java中ReentrantLock的使用.docx

    重入锁ReentrantLock 相对来说是synchronized、Object.wait()和Object.notify()方法的替代品(或者说是增强版),在JDK5.0的早期版本,重入锁的性能远远好于synchronized,但从JDK6.0开始,JDK在synchronized上做了...

    Java理论与实践:JDK 5.0中更灵活、更具可伸缩性的锁定机制

    本文介绍了多线程和并发性并不是什么新内容,但是Java语言设计中的创新之一就是,它是第一个直接把跨平台...本文还简单介绍和比较了ReentrantLock和synchronized,以及在什么时候选择用ReentrantLock代替synchronized。

    第15讲 synchronized和ReentrantLock有什么区别呢?1

    在 Java 5 以前,synchronized 是仅有的同步手段,在代码中, synchronized 可以用来修饰方法,也可以使用在特定的代码块儿上,本质上

    JAVA核心知识点整理(有效)

    25 JAVA8 与元数据.................................................................................................................................25 2.4. 垃圾回收与算法 .................................

    java核心知识点整理.pdf

    25 JAVA8 与元数据.................................................................................................................................25 2.4. 垃圾回收与算法 .................................

    带你看看Java的锁(一)-ReentrantLock

    带你看看Javad的锁-ReentrantLock前言ReentrantLock简介Synchronized对比用法源码分析代码结构方法分析SyncNonfairSyncFairSync非公平锁VS公平锁什么是公平非公平ReentrantLockReentrantLock的构造函数lock加锁方法...

    第15讲丨synchronized和ReentrantLock有什么区别呢?.html

    第15讲丨synchronized和ReentrantLock有什么区别呢?.html

    synchronized ReentrantLock volatile Atomic 原理分析.docx

    synchronized关键字是通过字节码指令来实现的 synchronized关键字编译后会在同步块前后形成monitorenter和monitorexit两个字节码指令 执行monitorenter指令时需要先获得对象的锁(每个对象有一个监视器锁...

    Lock接口与synchronized关键字

    Lock接口与synchronized关键字在Java并发编程中都是用于实现同步机制的重要工具,但它们在使用方式、功能特性以及灵活性等方面存在一些显著的差异。 首先,从使用方式上来看,synchronized是Java语言内置的关键字,...

    locks框架_ReentrantLock.pdf

    比较 Locks 框架与传统 synchronized 关键字的不同之处。 ReentrantLock 简介: 详细讲解 ReentrantLock 的概念和特点。解释为什么它被称为“可重入锁”,以及如何解决传统锁可能的问题。 ReentrantLock 的基本用法...

    wangwang4git#just-do#简单说说Synchronized,ReentrantLock1

    背景,应该就是Synchronized的缺点Synchronized产生原因,原子性(Atomicity)与可见性(visibility),其中可见性涉及到JM

    4.2019Android面试 常见58题.docx

    Android常见面试题 例如:java中==和equals和hashCode的区别 、ReentrantLock 、synchronized和volatile比较

    教你完全理解ReentrantLock重入锁

    在java关键字synchronized隐式支持重入性(关于synchronized可以看这篇文章),synchronized通过获取自增,释放自减的方式实现重入。与此同时,ReentrantLock还支持公平锁和非公平锁两种方式。 那么,要想完完全全的...

Global site tag (gtag.js) - Google Analytics