java基础温习 -- Thread synchronized关键字

synchronized 基本规则  

1. 当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程对“该对象”的该“synchronized方法”或者“synchronized代码块”的访问将被阻塞。

class MyRunable implements Runnable {

    public void run() {
        synchronized (this) { // this是指“当前的类对象” 此处为MyRunable对象 demo
            try {
                for (int i = 0; i < 5; i++) {
                    Thread.sleep(100); // 休眠100ms
                    System.out.println(Thread.currentThread().getName() + " loop " + i);
                }
            } catch (InterruptedException ie) {
            }
        }
    }
}

public class Demo1_1 {

    public static void main(String[] args) {
        Runnable demo = new MyRunable(); // 新建“Runnable对象”

        Thread t1 = new Thread(demo, "t1"); // 新建“线程t1”, t1是基于demo这个Runnable对象
        Thread t2 = new Thread(demo, "t2"); // 新建“线程t2”, t2是基于demo这个Runnable对象
        t1.start(); // 启动“线程t1”
        t2.start(); // 启动“线程t2”
    }
}
===========
t1 loop 0
t1 loop 1
t1 loop 2
t1 loop 3
t1 loop 4
t2 loop 0
t2 loop 1
t2 loop 2
t2 loop 3
t2 loop 4

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

3.  当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程对“该对象”的其他的“synchronized方法”或者“synchronized代码块”的访问将被阻塞。

  这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)。

synchronized 方法 和 synchronized 代码块

(假设P1、P2是同一个类的不同对象,类中定义了同步块或同步方法,P1 P2都可以调用它。)

Public synchronized void methodA()
{
    //….
}

  等同于

public void methodA()
{
synchronized (this)      // this指的就是调用这个方法的对象,如P1
{
       //…..
}
}

同步块:

public void method3(SomeObject so)
{
    synchronized(so) // 锁是so这个对象(当有一个明确的对象作为锁时,可以这样写)
    { 
       //….. 
    }
}

当有一个明确的对象作为锁时,就可以这样写程序,但当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的instance变量(它得是一个对象)来充当锁:

class Foo implements Runnable
{
        private byte[] lock = new byte[0]; // 零长度的byte数组充当锁
        Public void methodA() 
        {
           synchronized(lock) { 
        //
       }
} //….. }

synchronized 修饰static方法

Class Foo 
{
    public synchronized static void methodA()   // 同步的static方法
    { 
        //…. 
    }

    public void methodB() 
    {
       synchronized(Foo.class)   // 锁当前调用这个方法的对象所属的类
    } 
}

methodB()方法是把class literal作为锁的情况,它和同步的static函数产生的效果是一样的,取得的锁很特别,是当前调用这

个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了)

实例锁 和 全局锁
实例锁 -- 锁在某一个实例对象上。如果该类是单例,那么该锁也具有全局锁的概念。 实例锁对应的就是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() // 不能同时访问,都是锁的对象x
(2) x.isSyncA()与y.isSyncA()        // 可以同时访问,锁的不是同一个对象
(3) x.cSyncA()与y.cSyncB()         // 不能同时访问,static方法,两个都相当于Something.isSyncA()。锁的同一个类
(4) x.isSyncA()与Something.cSyncA()    // 可以同时访问,x.isSyncA()使用的是对象x的锁;而cSyncA()是静态方法,Something.cSyncA()可以理解对使用的是“类的锁”。
原文地址:https://www.cnblogs.com/eaglediao/p/7056822.html