synchronized的使用

Posted grow001

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了synchronized的使用相关的知识,希望对你有一定的参考价值。

概念:

是利用锁的机制来实现同步的。

锁机制有如下两种特性:

互斥性:即在同一时间只允许一个线程持有某个对象锁,通过这种特性来实现多线程中的协调机制,这样在同一时间只有一个线程对需同步的代码块(复合操作)进行访问。互斥性我们也往往称为操作的原子性。

可见性:必须确保在锁被释放之前,对共享变量所做的修改,对于随后获得该锁的另一个线程是可见的(即在获得锁时应获得最新共享变量的值),否则另一个线程可能是在本地缓存的某个副本上继续操作从而引起不一致。

为什么要使用synchronized:

在并发编程中存在线程安全问题,主要原因有:

1.存在共享数据

2.多线程共同操作共享数据。

synchronized的作用:

关键字synchronized可以保证在同一时刻,只有一个线程可以执行某个方法或某个代码块,同时synchronized可以保证一个线程的变化可见(可见性),即可以代替volatile。技术图片synchronized的用法

1.普通同步方法(实例方法),锁是当前实例对象 ,进入同步代码前要获得当前实例的锁

 public class synchronizedTest implements Runnable {
    static synchronizedTest instance=new synchronizedTest();
    static int i=0;
    @Override
    public void run() {
        //省略其他耗时操作....
        //使用同步代码块对变量i进行同步操作,锁对象为instance
        synchronized(instance){
            for(int j=0;j<10000;j++){
                i++;
            }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Thread t1=new Thread(instance);
        Thread t2=new Thread(instance);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(i);
    }
}

  

2.静态同步方法,锁是当前类的class对象 ,进入同步代码前要获得当前类对象的锁

(1)      同步非静态方法

 //修饰非静态方法

    //代码块1(对象)this指的是当前对象
    public  void accessResources1(){
        synchronized(this){
            try {
                synchronized (this){
                    TimeUnit.MINUTES.sleep(2);
                }
                System.out.println(Thread.currentThread().getName()+" is runing");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    //代码块1(CLASS类)
    public  void accessResources4(){
        synchronized(SynchroDemo01.class){//ClassLoader  class  ——-》堆   Class   所有的对象
           //有Class对象的所有的对象都共同使用这一个锁
            try {
                TimeUnit.SECONDS.sleep(2);
                System.out.println(Thread.currentThread().getName()+" is runing");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


    public static void main(String[] args) {
        final SynchroDemo01 deno01=new SynchroDemo01();
        for (int i = 0; i < 5; i++) {
            new Thread(deno01::accessResources1).start();
        }
    }

 

 

(2)      同步静态方法

public class synchronizedTest implements Runnable {
    //共享资源
    static int i =0;
    /**
     * synchronized 修饰实例方法
     */
    public static synchronized void increase(){
        i++;
    }
    @Override
    public void run(){
        for (int j =0 ; j<10000;j++){
            increase();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new synchronizedTest());
        Thread t2 = new Thread(new synchronizedTest());
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(i);
    }

根据获取的锁分类:

synchronized从锁的是谁的维度一共有两种情况:

  1. 锁住类

  2. 锁住对象实例

1)静态方法上的锁

静态方法是属于“类”,不属于某个实例,是所有对象实例所共享的方法。也就是说如果在静态方法上加入synchronized,那么它获取的就是这个类的锁,锁住的就是这个类

2)实例方法(普通方法)上的锁

实例方法并不是类所独有的,每个对象实例独立拥有它,它并不被对象实例所共享。这也比较能推出,在实例方法上加入synchronized,那么它获取的就是这个累的锁,锁住的就是这个对象实例

那锁住类还是锁住对象实例,

 

以上是关于synchronized的使用的主要内容,如果未能解决你的问题,请参考以下文章

同步代码 [重复]

#yyds干货盘点# Java | 关于synchronized相关理解

并发技术12线程锁技术的使用

Java并发编程实战—–synchronized

Java初识方法

多线程:synchronized代码块synchronized方法静态synchronized方法使用的锁