Synchronized基本使用

一、概述

  • 在多线程并发编程中Synchronized一直是元老级角色,很多人都会称呼它为重量级锁,但是随着Java SE1.6对Synchronized进行了各种优化(偏向锁、轻量级锁CAS)之后,有些情况下它并不那么重了。
  • Java SE1.6为了减少获得锁和释放锁所带来的性能消耗,引入了“偏向锁”和“轻量级锁”,所以在Java SE1.6里锁一共有四种状态,无锁状态,偏向锁状态,轻量级锁状态和重量级锁状态,它会随着竞争情况逐渐升级。锁可以升级但不能降级,意味着偏向锁升级成轻量级锁后不能降级成偏向锁。这种锁升级却不能降级的策略,目的是为了提高获得锁和释放锁的效率。

二、用法

  • 实例方法:锁住整个方法,整个方法都需要同步。
  • 静态方法:锁住整个方法,整个方法都需要同步。访问,所有对象实例上的线程都需要同步,这个同步静态方法,已经和类绑定。
  • 实例方法中的同步块:只锁同步块,方法中其余地方线程可以并发执行。
  • 静态方法中的同步块:只锁同步块,方法中其余地方线程可以并发执行。

三、注意事项

  • 静态方法中的同步块,只能锁class对象synchronized (SuspendTest.class)和静态引用成员变量,不能锁非静态实例对象例如:synchronized (this),编译不通过。

  • 实例方法中的同步块,既能锁住class对象和静态引用成员变量,也可以锁对象实例。

    • 锁住class对象或静态引用成员变量:所有对象实例上面的线程都需要同步执行。访问,所有对象实例上的线程都需要同步,这个同步静态代码块,已经和类绑定。
    • 锁住对象实例: 不同对象实例上面的线程互不干扰,可以并发执行。
  • 总之,只要synchronized和Class对象或者static扯上关系,访问,所有对象实例上的线程都需要同步。

四、测试代码

package test;

import java.util.concurrent.LinkedTransferQueue;

public class SuspendTest {

    private static void getSome(){
        //静态同步块,只能锁class,不可以锁实例
        synchronized (SuspendTest.class){
            System.out.println(Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void setSome(){
        //只有同步块需要线程同步执行,同步口外面的可以并发执行
        //System.out.println(Thread.currentThread().getName());
        synchronized (this){
            System.out.println(Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        SuspendTest suspendTest = new SuspendTest();
        suspendTest.test();
        //suspendTest.testStatic();
        SuspendTest suspendTest1 = new SuspendTest();
        suspendTest1.test();
        //suspendTest1.testStatic();
    }

    public void test(){
        new Thread(()->{setSome();}).start();
        new Thread(()->{setSome();}).start();
        new Thread(()->{setSome();}).start();
    }

    public static void testStatic(){
        new Thread(()->{getSome();}).start();
        new Thread(()->{getSome();}).start();
        new Thread(()->{getSome();}).start();
    }
}

你可能感兴趣的:(Synchronized基本使用)