高并发详解---synchronized 并发关键字

Synchronized作用:

官方:同步方法支持一种简单的策略来方式线程干扰和内存一致性错误,如果一个对象对多个线程可见,则对该对象变量所有的读取和写入都是同步方法完成的。

通俗:能够保证同一时刻最多只有一个线程执行改代码,以保证并发安全效果。

Synchronized地位:

关键字,是基本的同步互斥手段,并发编程必学内容。

不用并发的后果:

多线程情况下出现结果跟预期不符,我们称作线程不安全,例如下面结果不是我们想要的20000

public class DisAppearRequest1 implements Runnable{
    static  int i = 0;
    static DisAppearRequest1 instance = new DisAppearRequest1();

    public static void main(String[] args) throws Exception{
        Thread thread1 = new Thread(instance);
        Thread thread2 = new Thread(instance);
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println(i);
    }

    public void run() {
        for(int j=0;j<10000;j++){
            i++;
        }
    }
}

count++ ;它看上去只是一个操作,实际上包含了三个动作:

  1. 读取 count。
  2. 将 count 加1。
  3. 将 count的值写入到内存中。假设count为1,线程A进入该方法进行加1操作后count变成2,还未写入内存。线程B进入该方法      对读取的count依旧为1,进行加1后count也是2,因此无论是A还是B写入内存的数值都是2,预期中本来应该为3的数值变成了2

 用法介绍

对象锁:包括方法锁(默认锁对象为this当前实例对象)和同步代码块锁(自己指定锁对象)
类锁:指synchronized修饰静态的方法或指定锁为Class对象。

几种情况:

  •  两个线程同时访问同一个对象(同一个instance)的同步方法(Synchronized修饰),顺序执行,线程一执行结束,线程2执行,是对象锁的方法锁
  • 两个对象访问的是两个对象(两个实例)的同步方法,同步不起作用,相当于两个锁,每个实例有自己的锁,所以两个线程会是同时开始同时结束
  • 两个线程访问的是synchronized的静态方法,顺序执行,是类锁的static synchronized
  • 同时访问同步方法和非同步方法(一个被sychronized,一个没有),(线程是同一实例,线程一访问同步线程2访问非同步) , 两个线程同时执行,因为同步方法对非同步方法不会有任何影响
  • 访问同一个对象的不同的普通同步方法,因为是同一个对象,不同的同步方法默认都是this即当前的实例,所以存在线程等待释放,所以会是同步,是对象锁的同步方法 方法锁
  • 同时访问static synchronized 和非静态synchronized ,线程同时执行,他们所指定的锁对象是不一样的(没有加static的锁是this实例本身,加了static时锁是类锁,他背后的锁是.class对象)
  • 如果同时访问同步方法中包含了非同步方法,我觉得是同步的,因为入口同步方法不是放资源,也不能进入非同步方法,代码执行也是线程安全的 , (((但是老师解释一旦进入非同步方法就灭有锁了))

 

方法抛出异常后会释放锁吗(一旦抛出异常,第二个线程立即获得锁,立刻进入同步方法,意味着锁已经释放):不需要我们主动去释放锁,抛出异常后jvm释放了锁。

 这些信息都是从慕课网上听来的

原文地址:https://www.cnblogs.com/wygm/p/12201145.html