美文网首页
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