zoukankan      html  css  js  c++  java
  • 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()可以理解对使用的是“类的锁”。
  • 相关阅读:
    java中的 equals 与 ==
    String类的内存分配
    SVN用命令行更换本地副本IP地址
    npoi 设置单元格格式
    net core 微服务框架 Viper 调用链路追踪
    打不死的小强 .net core 微服务 快速开发框架 Viper 限流
    net core 微服务 快速开发框架 Viper 初体验20201017
    Anno 框架 增加缓存、限流策略、事件总线、支持 thrift grpc 作为底层传输
    net core 微服务 快速开发框架
    Viper 微服务框架 编写一个hello world 插件02
  • 原文地址:https://www.cnblogs.com/eaglediao/p/7056822.html
Copyright © 2011-2022 走看看