美文网首页
Synchronized 关键字

Synchronized 关键字

作者: 正规程序员 | 来源:发表于2019-01-19 12:25 被阅读89次

    Java多线程中的同步机制会对资源进行加锁,保证同一时刻只有一个线程操作该资源,避免多个线程同时访问该资源造成冲突。

    Synchronized是Java中的同步锁关键字,主要修饰的对象有:

    • 修饰非静态方法
      同步的是外部调用的实例对象,如new Sync()。多线程中不同实例调用a(),同步的是不同的Sync实例,同步无效。
    • 修饰静态方法
      同步的是包含此方法的类,如Sync.class。多线程中不同实例调用b(),同步的是同一个Sync.class,同步有效。
    • 修饰方法块
      同步的对象是synchronized(obj)内的非NULL的Object。
      • 若obj为Sync.class,则同步Sync.class本身,同理synchronized修饰静态方法;
      • 若obj为类属性,如string变量,则同步的是变量所属对象实例,即是外部调用的对象实例。

    修饰非静态方法示例:

        /**
         * a()方法是经过synchronized修饰的非静态方法,同步的是在外部调用的对象实例。
         * 由于外部多线程中是不同的对象实例,则对count的操作未实现同步(示例现象:未有序递减)。
         */
        public synchronized void a() {
            print();
        }
    

    修饰静态方法示例:

        /**
         * b()方法是经过synchronized修饰的静态方法,同步的是本类的对象实例,和外部多线程中的调用对象实例无关。
         * 外部多线程,谁先获得本类的对象锁,其他线程则处于阻塞状态,直到获得锁的线程解锁。
         */
        public static synchronized void b() {
            print();
        }
    

    修饰方法块示例:

        /**
         * c()和d()是静态方法和非静态方法的壳,内部synchronized修饰的是方法块。
         * 同步的对象是synchronized(obj)内的非NULL的Object。
         * 1.若obj为Sync.class,则同步Sync.class本身,同理synchronized修饰静态方法;
         * 2.若obj为类属性,如string变量,则同步的是变量所属对象实例,即是外部调用的对象实例。
         */
        public void c() {
            synchronized (string) {
                print();
            }
        }
    
        public static void d() {
            synchronized (Sync.class) {
                print();
            }
        }
    

    外部多线程中不同对象实例的调用:

        Count.INSTANT.count = 100;
        new Thread(() -> new Sync().a()).start();
        new Thread(() -> new Sync().a()).start();
    

    print打印操作如下:

        public static void print() {
            while (Count.INSTANT.count > 0) {
                Count.INSTANT.count = Count.INSTANT.count - 1;
                Log.d("Sync", "count = " + Count.INSTANT.count);
            }
        }
    

    单一数据源如下:

    /**
     * 序列化单例模式,确保操作的是单一数据源
     */
    public enum Count {
        INSTANT;
        public int count;
    }
    

    补充知识点

    • 类的静态成员变量和方法,是存储在方法区的,使用时均不用创建对象,在类加载初始化后即可使用。
    • 类的非静态成员变量在类的实例化时分配内存并初始化,届时才可调用。非静态成员的值存放在堆区,其中基本数据类型直接保存值,复杂类型保存指向堆对象的引用。

    相关文章

      网友评论

          本文标题:Synchronized 关键字

          本文链接:https://www.haomeiwen.com/subject/lunadqtx.html