专栏首页mini188学习笔记:java线程安全

学习笔记:java线程安全

首先得明白什么是线程安全:

线程安全编程中的术语,指某个函数 (计算机科学)函数库多线程环境中被调用时,能够正确地处理各个线程局部变量,使程序功能正确完成。

这是维基百科里的资料,看完后还不是特别的明白。我自己的理解就是在多线程环境下,某块代码中访问的资源不会发生冲突。

写这篇笔记的起因是上周的支付宝电话面试中问了我一个线程安全的问题,就是有一个类,他的方法A是加了synchronized关键字的,然后分别创建这个类的两个实例,请问,当多个线程同时访问这两个实例中的方法A时synchronized会起作用吗?

当时我的回答还是很明确而自信的说“会”,今天觉得这个问题要好好研究一下,于是就写了代码做了一下测试,发现自己答错了,这或许是我面试失败的原因之一吧。代码贴出来:

class Thread2 extends Thread{
    public void run() {
        MyObj obj = new MyObj();
        try {
            obj.sayHello(3000);//3秒
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class Thread3 extends Thread{
    public void run() {
        MyObj obj = new MyObj();
        try {
            obj.sayHello(1000);//1秒
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class MyObj {    public synchronized void sayHello(int delay) throws InterruptedException{        
        Thread.sleep(delay);
        System.out.println("delay" + delay);
    }
}
public class ThreadTest {
      public static void main(String[] args) throws Exception{
        Thread2 t2 = new Thread2();
        Thread3 t3 = new Thread3();
        t2.start();//先让t2线程启动,因为t2要等待3秒,如果线程同步有作用的话t3会处理阻塞状态
        t3.start();
      }
}

代码中的MyObj类就是我用于测试的线程安全的对象,它包含了一个sayHello方法,他是带有synchronized关键字的。但测试结果却是

delay1000 delay3000

这说明关键字没有起作用,也说明了不同的对象实例synchronized方法时是线程不安全的。知道这个结果心里有些难过,只不过事情已经过去就当是学习了经验吧。

synchronized除了修饰方法外,还可以修饰代码块,那就试试看吧,写了一个新的类:

class MyObj2 {
    private static Object lockObj = new Object();
    public void sayHello(int delay) throws InterruptedException{        
        synchronized(lockObj){
            Thread.sleep(delay);
            System.out.println("delay" + delay);
        }
    }
}

用这个类做测试的结果:

delay3000 delay1000

这说明synchronized修改代码块时线程同步是起作用的,但这里要注意,采用synchronized代码块时,synchronized(lockObj)中的lockObj对象是一个静态对象,所以他们对应的锁是同一个,这就可以实现线程间的同步。如果换成synchronized(this)又无法同步。

于是就得想明白为什么会有这两种差别呢?原来JAVA中每个对象都对应一个锁,synchronized关键字是通过检查这个对象锁的状态来调度的。这下就明白了,原来关键就在于对象对应的那个锁,MyObj之所以不能同步是因为创建了两不同的对象实例,自然对应的对象锁就不同,而synchronized修饰的是方法时,其对应检查的是当前对象的锁,所以就会出现不同步的情况。

后来在网上查资料的同时也发现一个叫类锁的东东,通过类锁获得的类本身,是唯一的,那么就应该是可以同步了,代码如下:

class MyObj3 {
    public synchronized static void sayHello(int delay) throws InterruptedException{
        Thread.sleep(delay);
        System.out.println("delay" + delay);
    }
}

得到的结果

delay3000 delay1000

这说明已经同步了,synchronized+static一起修改时获得的是类锁,获得类本身,所以只有一个,那么同步自然有了效果。

注:“光之子”在评论中指出了本文的一些问题,有兴趣的朋友看到本文请把评论也看看吧。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • ThreadLocal简单理解

    在java开源项目的代码中看到一个类里ThreadLocal的属性: private static ThreadLocal<Boolean> clientMod...

    用户1105954
  • 学习笔记: Delphi之线程类TThread

    新的公司接手的第一份工作就是一个多线程计算的小系统。也幸亏最近对线程有了一些学习,这次一接手就起到了作用。但是在实际的开发过程中还是发现了许多的问题,比如挂起与...

    用户1105954
  • 学习AOP之认识一下Spring AOP

    心碎之事 要说知道AOP这个词倒是很久很久以前了,但是直到今天我也不敢说非常的理解它,其中的各种概念即抽象又太拗口。 在几次面试中都被问及AOP,但是真的没有...

    用户1105954
  • 死磕Synchronized底层实现

    关于synchronized的底层实现,网上有很多文章了。但是很多文章要么作者根本没看代码,仅仅是根据网上其他文章总结、照搬而成,难免有些错误;要么很多点都是一...

    Java团长
  • 死磕Synchronized底层实现,面试你还怕什么?

    关于synchronized的底层实现,网上有很多文章了。但是很多文章要么作者根本没看代码,仅仅是根据网上其他文章总结、照搬而成,难免有些错误;要么很多点都是一...

    李红
  • 死磕Synchronized底层实现

    关于synchronized的底层实现,网上有很多文章了。但是很多文章要么作者根本没看代码,仅仅是根据网上其他文章总结、照搬而成,难免有些错误;要么很多点都是一...

    java思维导图
  • CTF从入门到提升(五) 部分截取函数及bool型盲注相关例题分析

    语句结构id=1 ,我们去做判断的时候是id=1 and 1=1,and 1=1的本质是返回一个true,true可以用1来代替,正常回显。我们很多时候就会去接...

    牛油果
  • Java多线程学习(三)——synchronized(上)

    在前两节的《Java多线程学习(一)——多线程基础》和《Java多线程学习(二)——Thread类的方法介绍》中我们接触了线程安全和非线程安全的概念,这节就来学...

    小森啦啦啦
  • 开始第一个QQ机器人【适用于v1.8】

    本示例将会使用”嘤鹉学舌”这个小插件的实现来演示如何使用Newbe.Mahua实现第一个机器人插件。

    newbe36524
  • Newbe.Mahua 插件热更新

    在阅读本教程之前,想必开发者已经学会了如何插件插件项目。因此本节只将本示例使用的关键参数和代码贴出。

    newbe36524

扫码关注云+社区

领取腾讯云代金券