相同点

  1. 都是可重入锁。
  2. 都保证了可见性和互斥性。

不同点

  1. 实现不同:  synchronized是Java中的关键字,是 JVM 层面通过监视器(Monitor)实现的;ReentrantLock是标准库的一个类,是通过 AQS(AbstractQueuedSynchronizer)程序级别的 API 实现。
  2. 用法不同:synchronized可以修饰普通方法和静态方法和代码块ReentrantLock只能用于代码块。
  3. 类型不同:synchronized 属于非公平锁ReentrantLock 既可以是公平锁也可以是非公平锁。默认情况下 ReentrantLock 为非公平锁。
  4. 获取和释放锁的方式不同:synchronized是自动加锁,已经执行完后释放锁ReentrantLock是需要通过手动加锁和释放锁。

synchronized和ReentrantLock例子

现在举例说明这两个锁的简单使用方法。

1)synchronized锁例子:

//Synchronized锁例子
public class SynchronizedLockExample extends Thread {
    public static  Integer count=1;
    public static final String lock = "CountLock";

    public SynchronizedLockExample() { }

    @Override
    public void run() {
        while(true){
            synchronized(lock){
                if (count>20){
                    System.out.println(getName() + "退出,count值: "+count);
                    break;
                }
                System.out.println(getName() + ",count值"+count);
                count = count +1;
            }
            //sleep放在synchronized外面
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String args[]) throws InterruptedException {
        SynchronizedLockExample task1 = new SynchronizedLockExample();
        SynchronizedLockExample task2 = new SynchronizedLockExample();

        task1.start();
        task2.start();

    }

}

测试一下

2)ReentrantLock例子:

public class ReentrantLockExample extends Thread {
    public static  Integer count=1;
    private static final Lock lock = new ReentrantLock();

    public ReentrantLockExample() { }

    @Override
    public void run() {
        while(true){
            if (count>10){
                System.out.println(getName() + "退出,count值: "+count);
                break;
            }

            try {
                lock.lock();
                System.out.println(getName() + ",count值"+count);
                count = count +1;
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
               lock.unlock();
            }

            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }

    }

    public static void main(String args[]) throws InterruptedException {
        ReentrantLockExample task1 = new ReentrantLockExample();
        ReentrantLockExample task2 = new ReentrantLockExample();

        task1.start();
        task2.start();

    }

} 

测试一下

点击测试一下,我们看到运行count的运行结果是顺序执行,解决了并发安全的问题,如果我们把代码
//lock.lock();
//lock.unlock();
注释掉,再次运行count值就不是线程安全的,肯能存在争用。