synchronized
线程安全问题的主要诱因?
1、存在共享数据(也称 临界资源)
2、存在多条线程共同操作这些共享资源
解决问题的根本方法:
同一时刻有且只有一条线程处理这些共享数据,其他线程只有等到改线程处理完,才能对共享数据进行操作。
互斥锁的特性:
互斥性:即是在同一时间只允许一个线程持有某个对象锁,通过这种特性来实现多线程的协调机制。这样在同一时间只有一个线程对需要同步的代码块(复合操作)进行访问。互斥性也被称为操作的原子性。
可见性:必须确保在锁被释放之前,对共享对象所做的修改。对于随后获得该锁的另一个线程是可见的(即在获得锁时,应获得共享变量最新的值),否则另一个线程可能是在本地缓存的某个副本上继续操作。从而引起不一致。
synchronized 锁的不是代码,锁的是对象。
根据获取锁的分类:
一、获取对象锁
获取对象锁的两种方法:
1、同步代码块:(synchronized (this) ,synchronized (类实例对象) ),锁是小括号()中的对象。
2、同步非静态方法:(synchronized method),锁是当前对象的实例对象。
获取类锁
获取类锁的两种用法:
1、同步代码块:(synchronized (类.class) )。锁是小括号()中的类对象
2、同步静态方法:(synchronized static method),锁是当前对象的类对象(Class对象)。
- public class SyncThread implements Runnable {
- @Override
- public void run() {
- String threadName = Thread.currentThread().getName();
- if (threadName.startsWith("A")) {
- async();
- } else if (threadName.startsWith("B")) {
- syncObjectBlock1();
- } else if (threadName.startsWith("C")) {
- syncObjectMethod1();
- } else if (threadName.startsWith("D")) {
- syncClassBlock1();
- } else if (threadName.startsWith("E")) {
- syncClassMethod1();
- }
- }
- /**
- * 异步方法
- */
- private void async() {
- try {
- System.out.println(Thread.currentThread().getName() + "_Async_Start: " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
- Thread.sleep(1000);
- System.out.println(Thread.currentThread().getName() + "_Async_End: " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- /**
- * 方法中有 synchronized(this|object) {} 同步代码块
- */
- private void syncObjectBlock1() {
- System.out.println(Thread.currentThread().getName() + "_SyncObjectBlock1: " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
- synchronized (this) {
- try {
- System.out.println(Thread.currentThread().getName() + "_SyncObjectBlock1_Start: " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
- Thread.sleep(1000);
- System.out.println(Thread.currentThread().getName() + "_SyncObjectBlock1_End: " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- /**
- * synchronized 修饰非静态方法
- */
- private synchronized void syncObjectMethod1() {
- System.out.println(Thread.currentThread().getName() + "_SyncObjectMethod1: " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
- try {
- System.out.println(Thread.currentThread().getName() + "_SyncObjectMethod1_Start: " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
- Thread.sleep(1000);
- System.out.println(Thread.currentThread().getName() + "_SyncObjectMethod1_End: " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- private void syncClassBlock1() {
- System.out.println(Thread.currentThread().getName() + "_SyncClassBlock1: " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
- synchronized (SyncThread.class) {
- try {
- System.out.println(Thread.currentThread().getName() + "_SyncClassBlock1_Start: " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
- Thread.sleep(1000);
- System.out.println(Thread.currentThread().getName() + "_SyncClassBlock1_End: " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- private synchronized static void syncClassMethod1() {
- System.out.println(Thread.currentThread().getName() + "_SyncClassMethod1: " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
- try {
- System.out.println(Thread.currentThread().getName() + "_SyncClassMethod1_Start: " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
- Thread.sleep(1000);
- System.out.println(Thread.currentThread().getName() + "_SyncClassMethod1_End: " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- public class SyncDemo {
- public static void main(String... args) {
- SyncThread syncThread = new SyncThread();
- Thread A_thread1 = new Thread(syncThread, "A_thread1");
- Thread A_thread2 = new Thread(syncThread, "A_thread2");
- Thread B_thread1 = new Thread(syncThread, "B_thread1");
- Thread B_thread2 = new Thread(syncThread, "B_thread2");
- Thread C_thread1 = new Thread(syncThread, "C_thread1");
- Thread C_thread2 = new Thread(syncThread, "C_thread2");
- Thread D_thread1 = new Thread(syncThread, "D_thread1");
- Thread D_thread2 = new Thread(syncThread, "D_thread2");
- Thread E_thread1 = new Thread(syncThread, "E_thread1");
- Thread E_thread2 = new Thread(syncThread, "E_thread2");
- A_thread1.start();
- A_thread2.start();
- B_thread1.start();
- B_thread2.start();
- C_thread1.start();
- C_thread2.start();
- D_thread1.start();
- D_thread2.start();
- E_thread1.start();
- E_thread2.start();
- }
- }