Synchronized和ReentrantLock

java synchronized知识点

synchronized相信学过java并发编程的小伙伴一定不会陌生,synchronized用来控制中线程的同步。
线程安全性:当多个线程同时访问一个类的(对象或者方法),这个类总是表现出正确的行为,则称这个类是线程安全的。

  • synchronized的含义
    1.互斥性
    synchronized用来修饰方法,代码块。
    修饰普通成员方法时,取得的对象锁是调用该方法的对象。
    修饰静态方法时,取得的对象锁是该类的class对象(存在于方jvm的方法区,只有一个)
    修饰代码块的时,对象锁需要开发者自行指定。注意:该对象一定要为共享的,不然线程不安全。
    2.内存可见性
    synchronzied除了互斥的含义之外,还有可见性的含义。
  • synchronized的特性
    1.可重入性
    重入的一种实现方法:为每一个锁关联一个计数值和一个所有者线程。当计数值为0的时候代表该锁不被任何线程持有。当一个线程请求一个未被持有的锁时,JVM将记下锁的持有者,并将计数值加一。当同一个线程再次获取这个锁的时候,计数值递增,当线程退出同步代码块的时候,计数器递减。当为0的时候,这个锁被释放。
    第一个例子:

public class UseSynchronized {
public synchronized void method1(){
System.out.println("进入方法1");
method2();
}
public synchronized void method2(){
System.out.println("进入方法2");
method3();
}
public synchronized void method3(){
System.out.println("进入方法3");
}
public static void main(String[] args) {
final UseSynchronized us=new UseSynchronized();
us.method1();
}
}
第二个例子:java
public class UseSynchronized {
private class A{
public synchronized void test(){
System.out.println("这是父类的方法");
}
}
class B extends A{
public synchronized void test(){
System.out.println("这是子类的方法");
super.test();
}
}
public static void main(String[] args) {
B b=new UseSynchronized().new B();
b.test();
}
}
```
2.悲观锁、独占锁
使用synchronized关键字来保证线程安全性的时候,将会使线程串行化调用方法或者执行代码块。这也就是一些同步类容器例如vector、hashtable效率不高的原因。

java ReentrantLock知识点

  • ReentrantLock的含义
    1.ReentrantLock与synchronized不同的地方在于它是一种显示锁,需要手动的lock,unlock,它有自己的condition
    2.ReentrantLock也是一种悲观锁

很多人认为ReentrantLock和synchronized比较,前者性能要比后者性能高很多,其实java1.8以后对synchronized性能进行了优化,使其和ReentrantLock的性能相差不多。

package org.lock;

import java.util.Random;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

abstract class Accumulator{
    public static long cycles=50000L;
    private static final int N=5;
    public static ExecutorService exec=Executors.newFixedThreadPool(N*2);
    private static CyclicBarrier barrier=new CyclicBarrier(N*2+1);
    protected volatile int index=0;
    protected volatile long value=0;
    protected long duration=0;
    protected String id="error";
    protected final static int SIZE=100000;
    protected static int[] preLoaded=new int[SIZE];
    static{
        Random rand=new Random(47);
        for(int i=0;i=SIZE){
            index=0;
        }
    }

    @Override
    public long read() {
        return value;
    }
}
class SynchronizedTest extends Accumulator{
    {
        id="synchronized";
    }

    @Override
    public synchronized void accumulate() {
        value+=preLoaded[index++];
        if(index>=SIZE){
            index=0;
        }
    }

    @Override
    public synchronized long read() {
        return value;
    }
    
}
class LockTest extends Accumulator{
    {
        id="Lock";
    }
    private Lock lock=new ReentrantLock();
    
    @Override
    public void accumulate() {
        lock.lock();
        try{
            value+=preLoaded[index++];
            if(index>=SIZE){
                index=0;
            }
        }finally{
            lock.unlock();
        }
    }

    @Override
    public long read() {
        lock.lock();
        try{
            return value;
        }finally{
            lock.unlock();
        }
    }
}
public class SynchronizationComparisons {
    static SynchronizedTest synch=new SynchronizedTest();
    static LockTest lock=new LockTest();
    static void test(){
        System.out.println("==========================");
        System.out.println("Cyccle"+"  "+Accumulator.cycles);
        synch.timeTest();
        lock.timeTest();
        Accumulator.report(synch, lock);
    }
    public static void main(String[] args) {
        int iterations=5;
        if(args.length>0){
            iterations=new Integer(args[0]);
        }
        System.out.println("Warmup");
        for(int i=0;i

运行结果:


Synchronized和ReentrantLock_第1张图片
两种锁性能比较.png

从运行结果可以看出,ReentrantLock性能比Synchronized好一点,但也好不太多。(运行环境:JDK1.8)

ReentrantLock之所以比synchronized好的地方在于不是它的性能,而是它的多condition,这是synchronized不能比较的。例如ArrayBlockingQueue中就是用的ReentrantLock,里面有两个condition

Synchronized和ReentrantLock_第2张图片
condition.png

总结:并不是所有的地方的都适合用ReentrantLock,具体使用什么要根据生产环境确定。

你可能感兴趣的:(Synchronized和ReentrantLock)