文档章节

多线程(2)-使用synchronized进行线程同步

haoran_10
 haoran_10
发布于 2016/07/15 16:36
字数 995
阅读 23
收藏 1

前文:java中多线程的锁,分为两种,悲观锁和乐观锁。使用synchronized作为锁的形式,就是悲观锁,又称为同步锁。

 

一、synchronized原理

  • 在java中,每一个对象有且仅有一个同步锁。同步锁是依赖于对象而存在。
  • 当我们调用某对象的synchronized方法时,就获取了该对象的同步锁。
  • 不同线程对同步锁的访问是互斥的。

通俗一点:N个线程同时访问对象A的方法时,如果线程X获得了对象A的同步锁,线程X可以执行A对象的synchronized方法,或者A对象的synchronized代码块。

其他线程不能访问A对象的synchronized方法,或者A对象的synchronized代码块,只可以访问对象A的非同步方法或者代码。其他线程只能等待线程X执行完方法之后,线程X释放了对象A的同步锁,其他线程获得对象A的同步锁,才可以执行A对象的synchronized方法,或者A对象的synchronized代码块。

推导出三个基本规则:

  1. 当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程对“该对象”的该“synchronized方法”或者“synchronized代码块”的访问将被阻塞。
  2. 当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程仍然可以访问“该对象”的非同步代码块。
  3. 当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程对“该对象”的其他的“synchronized方法”或者“synchronized代码块”的访问将被阻塞。

 

 二、synchronized方法 和 synchronized代码块

“synchronized方法”是用synchronized修饰方法,而 “synchronized代码块”则是用synchronized修饰代码块。

synchronized方法示例

public synchronized void foo1() {
    System.out.println("synchronized methoed");
}

synchronized代码块

public void foo2() {
    synchronized (this) {
        System.out.println("synchronized methoed");
    }
}

synchronized代码块中的this是指当前对象。也可以将this替换成其他对象,例如将this替换成obj,则foo2()在执行synchronized(obj)时就获取的是obj的同步锁。

 

三、 实例锁 和 全局锁

实例锁 -- 锁在某一个 实例对象上。如果该类是单例,那么该锁也具有全局锁的概念。

               实例锁对应的就是synchronized关键字。

全局锁 -- 该锁针对的是 ,无论实例多少个对象,那么线程都共享该锁。

               全局锁对应的就是static synchronized(或者是锁在该类的class或者classloader对象上)。

关于“实例锁”和“全局锁”有一个很形象的例子:

pulbic class Something {
    public synchronized void isSyncA(){}
    public synchronized void isSyncB(){}
    public static synchronized void cSyncA(){}
    public static synchronized void cSyncB(){}
}

假设,Something有两个实例x和y。下面4组表达式获取的锁的情况。

(1)、x.isSyncA()与x.isSyncB()   

不能被同时访问。因为isSyncA()和isSyncB()都是访问同一个对象(对象x)的同步锁

(2)、x.isSyncA()与y.isSyncA()

 可以同时被访问。因为访问的不是同一个对象的同步锁,x.isSyncA()访问的是x的同步锁,而y.isSyncA()访问的是y的同步锁。

(3)、 x.cSyncA()与y.cSyncB()

不能被同时访问。因为cSyncA()和cSyncB()都是static类型,x.cSyncA()相当于Something.isSyncA(),y.cSyncB()相当于Something.isSyncB(),因此它们共用一个同步锁,不能被同时访问。

(4)、x.isSyncA()与Something.cSyncA()

可以被同时访问。因为isSyncA()是实例方法,x.isSyncA()使用的是对象x的锁;而cSyncA()是静态方法,Something.cSyncA()可以理解对使用的是“类的锁”。因此,它们是可以被同时访问的。

 

 

四、小结

线程本身是没有锁的,

锁在对象身上,每个对象只有一把同步锁,

如果线程希望执行对象的同步方法,或者同步代码块,线程就必须获得对象的同步锁,才能执行对象的同步方法,才能安全有序的共享对象资源。

 

© 著作权归作者所有

共有 人打赏支持
haoran_10
粉丝 25
博文 88
码字总数 80846
作品 0
杭州
程序员
私信 提问
多线程编程学习二(对象及变量的并发访问).

一、概念 非线程安全:会在多个线程对同一个对象中的实例变量进行并发访问时发生,产生的后果就是"脏读",也就是取到的数据其实是被更改过的. 线程安全:获得的实例变量的值是经过同步处理的...

jmcui
2017/09/09
0
0
线程同步与死锁

一.多线程共享数据 在多线程的操作中,多个线程有可能同时处理同一个资源,这就是多线程的共享数据。 二.线程同步 解决数据共享的安全问题,必须使用同步,所谓同步就是指多个线程在同一个时...

tank_99
2016/11/22
0
0
synchronized与ThreadLocal

synchronized是实现java的同步机制。同步机制是为了实现同步多线程对相同资源的并发访问控制。保证多线程之间的通信。 同步的主要目的是保证多线程间的数据共享。同步会带来巨大的性能开销,...

bigYuan
2013/07/18
0
2
Synchronized同步的考虑

当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。 2种使...

长平狐
2013/01/06
58
0
Java多线程学习(二)synchronized关键字(2)

系列文章传送门: Java多线程学习(一)Java多线程入门 Java多线程学习(二)synchronized关键字(1) java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Ja...

一只蜗牛呀
2018/04/16
0
0

没有更多内容

加载失败,请刷新页面

加载更多

乱入Linux界的我是如何学习的

欢迎来到建哥学Linux,咳!咳!咳!开个玩笑哈,我是一个IT男,IT界的入门选手,正在学习Linux。 在之前,一直想进军IT界,学习IT技术,但是苦于没有人指导,也不知道学什么,最开始我自己在...

linux-tao
36分钟前
0
0
乱入Linux界的我是如何学习的

欢迎来到建哥学Linux,咳!咳!咳!开个玩笑哈,我是一个IT男,IT界的入门选手,正在学习Linux。 在之前,一直想进军IT界,学习IT技术,但是苦于没有人指导,也不知道学什么,最开始我自己在...

linuxprobe16
今天
9
0
OSChina 周日乱弹 —— 没时间 没头发 但有钱

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @开源中国总经办主任 :分享齐一的单曲《这个年纪》 《这个年纪》- 齐一 手机党少年们想听歌,请使劲儿戳(这里) @肿肿卷 :我真的可以睡一天...

小小编辑
今天
83
6
Django进阶 1.1 ORM基础—ORM 1.2.1 增删改查之查询 1.2.2 删改增 (1) 1.2.3 删改增 (2)

ORM基础 ORM是Django操作数据库的API,Django的作者将sql语句封装在里面供我们使用。 我们前面还提到过Django提供一个模拟数据库的工具,sqlite,供我们学习测试使用。 如果我们想使用mysql...

隐匿的蚂蚁
今天
3
0
Windows 上安装 Scala

在安装 Scala 之前需要先安装 Java 环境,具体安装的详细方法就不在这里描述了。 您可以自行搜索我们网站中的内容获得其他网站的帮助来获得如何安装 Java 环境的方法。 接下来,我们可以从 ...

honeymose
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部