• 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()可以理解对使用的是“类的锁”。
  • 相关阅读:
    自动称重系统-3
    自动称重系统-2
    自动称重系统-1
    Qt-序列号生成器
    征战 OSG-序及目录
    Qt-QML-安卓编译问题
    OSG-OSG中的observer_ptr指针
    HZNU Training 22 for Zhejiang Provincial Competition 2020
    树上乱搞
    HZNU Training 21 for Zhejiang Provincial Competition 2020
  • 原文地址:https://www.cnblogs.com/eaglediao/p/7056822.html
Copyright © 2020-2023  润新知