要了解synchronized的原理及应用场景就得先了解并发编程是什么,对并发编程不了解的话可以看看这篇博客:https://blog.csdn.net/dekulugu/article/details/108754623
一、synchronized的基本使用
-
为什么要使用synchronized?
在并发编程中存在线程安全问题,主要原因有:1.存在共享数据 2.多线程共同操作共享数据。synchronized关键字可以保证在同一时刻,只有一个线程可以执行某个方法或代码块,同时synchronized可以保证一个线程的变化可见(可见性),即可以代替volatile。
这里简单提一下volatile:volatile 的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略。(编译器为了加快程序运行的速度,对一些变量的写操作会先在寄存器或者是CPU缓存上进行,最后才写入内存.
而在这个过程,变量的新值对其他线程是不可见的.而volatile的作用就是使它修饰的变量的读写操作都必须在内存中进行!) -
synchronized的三种应用方式
Java中每一个对象都可以作为锁,这是synchronized实现同步的基础:
-
普通同步方法(实例方法),锁是当前实例对象 ,进入同步代码前要获得当前实例的锁
示例代码1:多个线程访问同一个对象的同一个方法
public class synchronizedTest implements Runnable { //共享资源 static int i =0; /** * synchronized 修饰实例方法 */ public synchronized void increase(){ i++; } @Override public void run(){ for (int j =0 ; j<10000;j++){ increase(); } } public static void main(String[] args) throws InterruptedException { synchronizedTest test = new synchronizedTest(); Thread t1 = new Thread(test); Thread t2 = new Thread(test); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(i); } }
结果:20000
分析:当两个线程同时对一个对象的一个方法进行操作,只有一个线程能够抢到锁。因为一个对象只有一把锁,一个线程获取了该对象的锁之后,其他线程无法获取该对象的锁,就不能访问该对象的其他synchronized实例方法,但是可以访问非synchronized修饰的方法示例代码2:一个线程获取了该对象的锁之后,其他线程来访问其他synchronized实例方法现象
public class SynchronizedTest { public synchronized void method1() { System.out.println("Method 1 start"); try { System.out.println("Method 1 execute"); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Method 1 end&#