首先得明白什么是线程安全:
线程安全编程中的术语,指某个函数 (计算机科学)函数库多线程环境中被调用时,能够正确地处理各个线程局部变量,使程序功能正确完成。
这是维基百科里的资料,看完后还不是特别的明白。我自己的理解就是在多线程环境下,某块代码中访问的资源不会发生冲突。
 
 
写这篇笔记的起因是上周的支付宝电话面试中问了我一个线程安全的问题,就是有一个类,他的方法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一起修改时获得的是类锁,获得类本身,所以只有一个,那么同步自然有了效果。

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

学习笔记:java线程安全的更多相关文章

  1. java学习笔记15--多线程编程基础2

    本文地址:http://www.cnblogs.com/archimedes/p/java-study-note15.html,转载请注明源地址. 线程的生命周期 1.线程的生命周期 线程从产生到消亡 ...

  2. JUC源码学习笔记5——线程池,FutureTask,Executor框架源码解析

    JUC源码学习笔记5--线程池,FutureTask,Executor框架源码解析 源码基于JDK8 参考了美团技术博客 https://tech.meituan.com/2020/04/02/jav ...

  3. [java学习笔记]java语言核心----面向对象之this关键字

    一.this关键字 体现:当成员变量和函数的局部变量重名时,可以使用this关键字来区别:在构造函数中调用其它构造函数 原理:         代表的是当前对象.         this就是所在函数 ...

  4. [java学习笔记]java语言核心----面向对象之构造函数

    1.构造函数概念 特点: 函数名与类名相同 不用定义返回值类型 没有具体的返回值 作用:                给对象进行初始化 注意: 默认构造函数 多个构造函数是以重载出现的 一个类中如果 ...

  5. 操作系统学习笔记----进程/线程模型----Coursera课程笔记

    操作系统学习笔记----进程/线程模型----Coursera课程笔记 进程/线程模型 0. 概述 0.1 进程模型 多道程序设计 进程的概念.进程控制块 进程状态及转换.进程队列 进程控制----进 ...

  6. java学习笔记14--多线程编程基础1

    本文地址:http://www.cnblogs.com/archimedes/p/java-study-note14.html,转载请注明源地址. 多线程编程基础 多进程 一个独立程序的每一次运行称为 ...

  7. java学习笔记之线程(Thread)

    刚开始接触java多线程的时候,我觉得,应该像其他章节的内容一样,了解了生命周期.构造方法.方法.属性.使用的条件,就可以结束了,然而随着我的深入学习了解,我发现java的多线程是java的一个特别重 ...

  8. (Java学习笔记) Java Threading (Java线程)

    Java Threading (Java线程) ● Process & Thread Processes are the abstraction of running programs: A ...

  9. JavaSE中线程与并行API框架学习笔记1——线程是什么?

    前言:虽然工作了三年,但是几乎没有使用到多线程之类的内容.这其实是工作与学习的矛盾.我们在公司上班,很多时候都只是在处理业务代码,很少接触底层技术. 可是你不可能一辈子都写业务代码,而且跳槽之后新单位 ...

  10. Java学习笔记 -- Java定时调度工具Timer类

    1 关于 (时间宝贵的小姐姐请跳过) 本教程是基于Java定时任务调度工具详解之Timer篇的学习笔记. 什么是定时任务调度 基于给定的时间点,给定的时间间隔或者给定的执行次数自动执行的任务. 在Ja ...

随机推荐

  1. 如何获取苹果手机的UDID

    获取苹果手机的UDID有很多种,比如Xcode,iTunes等等吧,个人比较推荐使用iTunes,因为比较官方,而且苹果电脑自带的有,而且Windows也可以下载安装. 1.下载安装itunes(点击 ...

  2. debug : 应用程序无法正常启动(0xc000007b)

  3. Google之Chromium浏览器源码学习——base公共通用库(一)

    Google的优秀C++开源项目繁多,其中的Chromium浏览器项目可以说是很具有代表性的,此外还包括其第三开发开源库或是自己的优秀开源库,可以根据需要抽取自己感兴趣的部分.在研究.学习该项目前的时 ...

  4. Hadoop单机模式安装-(1)安装设置虚拟环境

    网络上关于如何单机模式安装Hadoop的文章很多,按照其步骤走下来多数都失败,按照其操作弯路走过了不少但终究还是把问题都解决了,所以顺便自己详细记录下完整的安装过程. 此篇主要介绍如何在Windows ...

  5. AOJ 0121: Seven Puzzle【BFS】

    From: AOJ 0121 思路:与前几题的bfs不同,这次的bfs没有明确的移动对象,看似任意一个数都可以当成对象移动.这时我们只需要抓住一个格子就行,比如我们把0作为移动对象,那么0在地图中漫游 ...

  6. PhoneGap配置笔记

    关于PhoneGap简介: PhoneGap是一个用基于HTML,CSS和JavaScript的,创建移动跨平台移动应用程序的快速开发平台.它使开发者能够利用iPhone,Android,Palm,S ...

  7. UWP Composition API - 锁定列的FlexGrid

    需求是第一列锁定,那么怎么让锁定列不跟着滚动条向做移动呢? 其实很简单,让锁定列跟scrollviewer的滚动做反方向移动. 先看一下这个控件的模板,嗯,其实很简单,就是ListView的模板,不同 ...

  8. Java Web 项目目录规范

    一.项目结构 这里和其他项目区别不大,我将模板抽离出来,更容易分析和理解: 解释一下:js主要包括extends(引入第三方的js).module(项目模块自己的js).lib(引用包,这里也可以继续 ...

  9. iOS 可执行文件瘦身方法

    编译选项 1.编译器优化级别 Build Settings->Optimization Level有几个编译优化选项,release版应该选择Fastest, Smalllest,这个选项会开启 ...

  10. nginx:文件下载指定保存文件名的配置

    一般在我们上传完资源文件之后,为了避免文件名冲突,会将文件名改成毫无意义的一段字符.这个字符,可能是MD5产生的,或者是其他方式产生的字符串.这时候,下载的时候,默认保存的文件名会是这段毫无意义的文件 ...