区别:
1)Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;
2)synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;
3)Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;
4)通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。
5)Lock可以提高多个线程进行读操作的效率。
  在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。

synchronized实现的机理依赖于软件层面上的JVM,synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放。
ReentantLock继承接口Lock并实现了接口中定义的方法,除了能完成synchronized所能完成的所有工作外,还提供了诸如可响应中断锁、可轮询锁请求、定时锁等避免多线程死锁的方法。

尽管Java实现的锁机制有很多种,并且有些锁机制性能也比synchronized高,但还是强烈推荐在多线程应用程序中使用该关键字,因为实现方便,后续工作由JVM来完成,可靠性高。只有在确定锁机制是当前多线程程序的性能瓶颈时,才考虑使用其他机制,如ReentrantLock等。

ReentrantLock通过方法lock()与unlock()来进行加锁与解锁操作,与synchronized会被JVM自动解锁机制不同,ReentrantLock加锁后需要手动进行解锁。为了避免程序出现异常而无法正常解锁的情况,使用ReentrantLock必须在finally控制块中进行解锁操作。

关联问题: 加锁机制有哪几种?
参考代码:ReentrantLockTest

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockTest {
	public static ReentrantLock reenT = new ReentrantLock();// 参数默认false,不公平锁
	private static int count;

	/**
	 * 使用场景:(1)比如一个定时任务,第一次定时任务未完成,重复发起了第二次,直接返回flase;
	 * 
	 * tryLock()方法是有返回值的,它表示用来尝试获取锁,如果获取成功,则返回true,
	 * 如果获取失败(即锁已被其他线程获取),则返回false,
	 * 也就说这个方法无论如何都会立即返回。在拿不到锁时不会一直在那等待。
	 */
	public static void tryLockTest() {
		if (reenT.tryLock()) {
			// 如果已经被lock,则立即返回false不会等待,
			// 达到忽略操作的效果 ,当执行1000线程时,有些未获得对象锁的线程,会自动跳过
			try {
				// 操作
				System.out.println("得到了锁:" + Thread.currentThread().getName());
			} finally {
				// 释放锁
				reenT.unlock();
			}

		}
	}

	/**
	 * 使用场景:(1)同步操作 类似于synchronized 如果被其它资源锁定,会在此等待锁释放,达到暂停的效果
	 * ReentrantLock存在公平锁与非公平锁 而且synchronized都是公平的
	 */
	public static void lockTest() {
		try {
			reenT.lock(); // 如果被其它资源锁定,会在此等待锁释放,达到暂停的效果
			// 操作
			System.out.println("得到了锁:" + Thread.currentThread().getName());

		} finally {
			reenT.unlock();
		}
	}

	/**
	 * 使用场景:(1)如果发现该操作正在执行,等待一段时间,如果规定时间未得到锁,放弃。防止资源处理不当,线程队列溢出,出现死锁
	 */
	public static void trylockTimeTest() {
		try {
			if (reenT.tryLock(5, TimeUnit.SECONDS)) { // 如果已经被lock,尝试等待5s,看是否可以获得锁,如果5s后仍然无法获得锁则返回false继续执行
				try {
					// 操作
					System.out.println("aaaa:" + Thread.currentThread().getName());
				} finally {
					reenT.unlock();
				}
			}
		} catch (InterruptedException e) {
			e.printStackTrace(); // 当前线程被中断时(interrupt),会抛InterruptedException
		}

	}

	public static void main(String[] args) {
		// 同时启动1000个线程,去进行i++计算,看看实际结果
		for (int i = 0; i < 1000; i++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					ReentrantLockTest.tryLockTest();
//					ReentrantLockTest.lockTest();
				}
			}).start();
		}
	}
	
	public synchronized void run() {
		count++;
    }

}