Synchronized 和 Lock 的区别简单明了

一. 线程与进程:

在开始之前先把进程与线程进行区分一下,一个程序最少需要一个进程,而一个进程最少需要一个线程。关系是线程–>进程–>程序的大致组成结构。所以线程是程序执行流的最小单位,而进程是系统进行资源分配和调度的一个独立单位。以下我们所有讨论的都是建立在线程基础之上。

 

二.Thread的状态以及几个重要方法:

Thread的几个重要方法

a、start()方法,调用该方法开始执行该线程;

b、stop()方法,调用该方法强制结束该线程执行;

c、join方法,调用该方法等待该线程结束。

d、sleep()方法,调用该方法该线程进入等待。

e、run()方法,调用该方法直接执行线程的run()方法,但是线程调用start()方法时也会运行run()方法,区别就是一个是由线程调度运行run()方法,一个是直接调用了线程中的run()方法!!

除了这5种方法之外,其实我们常用的还有 wait()和notify()。要注意,其实wait()与notify()方法是Object的方法,不是Thread的方法!!同时,wait()与notify()会配合使用,分别表示线程挂起和线程恢复。

这里还有一个很常见的问题,就是  wait()与sleep()的区别,简单来说wait()会释放对象锁而sleep()不会释放对象锁。

 

线程总共有5大状态

  • 新建状态:新建线程对象,并没有调用start()方法之前
  • 就绪状态:调用start()方法之后线程就进入就绪状态,但是并不是说只要调用start()方法线程就马上变为当前线程,在变为当前线程之前都是为就绪状态。值得一提的是,线程在睡眠和挂起中恢复的时候也会进入就绪状态哦。
  • 运行状态:线程被设置为当前线程,开始执行run()方法。就是线程进入运行状态
  • 阻塞状态:线程被暂停,比如说调用sleep()方法后线程就进入阻塞状态
  • 死亡状态:线程执行结束

 

三.Synchronized 和 Lock 的区别

Java 中两种实现加锁的方式:一种是使用 synchronized 关键字,另一种是使用 Lock 接口的实现类。

synchronized 关键字就像是自动挡,可以满足一切的驾驶需求。 但是如果你想要做更高级的操作,比如玩漂移或者各种高级的骚操作,那么就需要手动挡,也就是 Lock 接口的实现类。

而 synchronized 在经过 Java 每个版本的各种优化后,效率也变得很高了。只是使用起来没有 Lock 接口的实现类那么方便。

两者的区别:

1. Synchronized是内置的 java 关键字,而 Lock 是一个 java 类

2. Synchronized 无法获取锁的状态, Lock 可以判断是否获取到了锁

3. Synchronized 会自动释放锁,Lock 必须要手动释放锁!如果不释放会造成死锁,需要lock()和unlock()方法配合try/finally语句块来完成

4. Synchronized 当线程 1 获得锁,其他线程会处于一直等待的状态;而 Lock 锁不一定会等待下去,通过lock.lockInterruptibly()来实现这个机制。如果持有锁的线程长期不释放,正在等待的线程可以选择放弃等待。

5. Synchronized 支持可重入锁,不可中断,非公平锁;Lock 支持可重入锁,默认为非公平锁(但是可以设置为公平锁)

6. Sychronized 适合锁少量的代码同步问题; Lock 适合锁大量的同步代码

 

 

本人觉得 Lock 锁中 ReenTrantLock类+Condition(条件)类,两者配合,从而可以唤醒指定的线程来执行操作。而不是像synchronized要么随机唤醒一个线程要么唤醒全部线程。

 

相似点:
这两种同步方式有很多相似之处,它们都是加锁方式同步,而且都是阻塞式的同步,也就是说当如果一个线程获得了对象锁,进入了同步块,其他访问该同步块的线程都必须阻塞在同步块外面等待,而进行线程阻塞和唤醒的代价是比较高的(操作系统需要在用户态与内核态之间来回切换,代价很高,不过可以通过对锁优化进行改善)。

在 Synchronized 优化以前,Synchronized 的性能是比 Lock 差很多的,但是自从Synchronized引入了偏向锁,轻量级锁(自旋锁)后,两者的性能就差不多了,在两种方法都可用的情况下,官方甚至建议使用 Synchronized,其实 Synchronized 的优化我感觉就借鉴了ReenTrantLock中的CAS技术。都是试图在用户态就把加锁问题解决,避免进入内核态的线程阻塞。

线程自旋和适应性自旋
我们知道,java’线程其实是映射在内核之上的,线程的挂起和恢复会极大的影响开销。并且jdk官方人员发现,很多线程在等待锁的时候,在很短的一段时间就获得了锁,所以它们在线程等待的时候,并不需要把线程挂起,而是让他无目的的循环,一般设置10次。这样就避免了线程切换的开销,极大的提升了性能。
而适应性自旋,是赋予了自旋一种学习能力,它并不固定自旋10次一下。他可以根据它前面线程的自旋情况,从而调整它的自旋,甚至是不经过自旋而直接挂起。
 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值