从不同步的代码块中调用了对象同步方法。_面试常问,一半以上的人容易忽略的,线程同步问题...

ace89b8abed39c4f924c1f0825c7ec4d.png

什么是线程同步?

当使用多个线程来访问同一个数据时,非常容易出现线程安全问题(比如多个线程都在操作同一数据导致数据不一致),所以我们用同步机制来解决这些问题。

3cd86cbca2ae1a5408ce999824b5829d.png

为什么要线程同步?

因为当我们有多个线程要同时访问一个变量或对象时,如果这些线程中既有读又有写操作时,就会导致变量值或对象的状态出现混乱,从而导致程序异常

同步机制:

在多线程中,可能有多个线程试图访问一个有限的资源,必须预防这种情况的发生。所以引入了同步机制:在线程使用一个资源时为其加锁,这样其他的线程便不能访问那个资源了,直到解锁后才可以访问。

Java多线程支持方法同步,方法同步只需用用synchronized来修饰方法即可,那么这个方法就是同步方法了。

五种同步线程的方法

1.同步方法:使用sychronized关键字修饰方法,由于java的每个对象都有一个内置锁,当用此关键字修饰方法(静态与非静态都可修饰)时,内置锁会保护整个方法,在调用该方法时,在调用该方法前,需要获得内置锁,否则就处于阻塞状态。

2.同步代码块:既有sychronized修饰的语句块,被该关键字修饰的语句块会被自动加上内置锁,从而实现同步。(注意:线程同步是一个高开销的操作,因此应当尽量减少同步的内容,通常没必要同步整个方法)

/*** 定义一个类,包含了线程类需要调用的方法 */
class Compute1{
 //通过同步代码块锁定object1对象进行锁定了其他同样的synchronized代码块
 private Object object1 = new Object();
 public void execute(){
 synchronized(object1){
 for(int i = 0; i<100; i++){
 try {
 Thread.sleep(100);
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 System.out.println("compute1:execute1 " + i++);
 }
 }
 
 }
 public synchronized void execute2(){
 synchronized(object1){
 for(int i = 0; i<100; i++){
 try {
 Thread.sleep(100);
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 System.out.println("compute1:execute2 " + i++);
 }
 }
 }}

如果想要使用synchronized同步代码块达到和使用synchronized方法同样的效果,可以锁定this引用:

synchronized(this){…}

3.使用特殊域变量(Volatile)实现线程同步.因为Volatile不能保证原子操作导致的,因此Volatile不能代替sychronized,此外Volatile会组织编译器对代码优化,因此不建议使用它,

4.使用重入锁对线同步(javaSE5.0以上中新增了一个java.util.concurrent包来支持同步)

5.使用局部变量实现线程同步

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值