`
haoran_10
  • 浏览: 442540 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

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

阅读更多
前文: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()可以理解对使用的是“类的锁”。因此,它们是可以被同时访问的。

 

 

四、小结

线程本身是没有锁的,

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

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

 

  • 大小: 73.6 KB
5
1
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics