java 在多线程并发编程中,为了线程安全,我们需要对线程数据进行同步,一般的实现方式就是synchronized和重入锁Lock(ReetrantLock,ReadWriterLock等)

共同点:

都是通过加锁方式来实现同步,而且都是阻塞式同步(也就是一个线程进入同步代码块,其他线程就在外面等待)。

区别:synchronized是java关键字,是原生态层面互斥,通过jvm层面实现,不但可以通过监控工具监控synchronized的锁定,当代码执行出现异常时,jvm会自动释放锁,而lock就不行;Lock是一个接口,java jDK 1.5之后推出的api层面互斥,lock通过代码来实现,要保证锁一定会被释放,必须放在lock ,unlock,try/catch/finnally语句中。

 Lock可以让等待锁的线程中断(主要使用Reentranlock重入锁),去干别的事,而synchronized就不行,使用synchronized时,线程会一直等待下去,不能够响应中断。

使用lock可以知道是否获取锁,而synchronized无法办到。(可以使用trylock方法返回值true(获取锁) 或 false(没有获取锁))

lock可以提高多线程进行读操作(主要使用ReadWriterLock读写锁)的效率。(例如lock可以实现多线程读线程间不发生冲突,而synchronized不能多线程同时读)

在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。

举个例子:当有多个线程读写文件时,读操作和写操作会发生冲突现象,写操作和写操作会发生冲突现象,但是读操作和读操作不会发生冲突现象。

  但是采用synchronized关键字来实现同步的话,就会导致一个问题:

  如果多个线程都只是进行读操作,所以当一个线程在进行读操作时,其他线程只能等待无法进行读操作。

  因此就需要一种机制来使得多个线程都只是进行读操作时,线程之间不会发生冲突,通过Lock就可以办到。

  另外,通过Lock可以知道线程有没有成功获取到锁。这个是synchronized无法办到的