定义
- Java中的关键字,是一种重量级同步锁
修饰的对象
修饰对象 作用对象
方法块 调用该代码块的对象 synchronized(this) {}
修饰方法 调用该方法的对象
静态方法 这个类的所有对象
类 这个类的所有对象
特点
- Synchronized 不能被继承
- 每个对象只有一个锁(lock)与之相关联,谁拿到这个锁谁就可以运行它所控制的那段代码
- 现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制
- (synchorized)锁分为对象锁(同步方法/同步代码块)和类锁(同步类/同步静态方法),两者之间互不干扰
- 一个对象只有一个锁
- 不同对象的对象锁是互不干扰的,但每一个类只有一个类锁
修饰方法快
-
用于修饰方法块,作用于该代码块的对象,在多线程情况下,当该对象在一个线程中被调用时,被锁住的内容只能由该线程执行,其他线程都处于等待状态,知道该线程执行完毕锁住内容,但是当该方法由非锁住的代码块时,其他线程是可以访问该方法的非锁住内容的
public class Counter implements Runnable{ private int count; public Counter() { count = 0; } public void countAdd() { synchronized(this) { for (int i = 0; i < 5; i ++) { try { Log.e("mj",Thread.currentThread().getName() + ":" + (count++)); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } } //非synchronized代码块,未对count进行读写操作,所以可以不用synchronized public void printCount() { for (int i = 0; i < 5; i ++) { try { Log.e("mj",Thread.currentThread().getName() + " count:" + count); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } @Override public void run() { String threadName = Thread.currentThread().getName(); if (threadName.equals("A")) { countAdd(); } else if (threadName.equals("B")) { printCount(); } } }
//调用
Counter counter = new Counter();
Thread thread1 = new Thread(counter, “A”);
Thread thread2 = new Thread(counter, “B”);
thread1.start();
thread2.start();
修饰方法
-
用于修饰方法,作用于该代码块的对象,在多线程情况下,当该对象在一个线程中被调用时,被锁住的内容只能由该线程执行,其他线程都处于等待状态
public class MyThread implements Runnable{
private static int count;public MyThread() { count = 0; } @Override public synchronized void run() { for (int i = 0; i < 5; i++) { try { Log.e("mj",Thread.currentThread().getName() + ":" + (count++)); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } public int getCount() { return count; }
}
//调用
MyThread syncThread = new MyThread();
Thread thread1 = new Thread(syncThread, “SyncThread1”);
Thread thread2 = new Thread(syncThread, “SyncThread2”);
thread1.start();
thread2.start();
修饰静态方法
-
用于修饰静态方法,作用于该类的所有对象,在多线程情况下,无论线程持有该类的那个对象,在同一时刻只有一个线程可以访问,其他线程无论是否是有同一对象,都必须处于等待状态
public class MyThread implements Runnable{ private static int count; public MyThread() { count = 0; } @Override public void run() { method(); } public synchronized static void method() { for (int i = 0; i < 5; i ++) { try { Log.e("mj",Thread.currentThread().getName() + ":" + (count++)); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } } //调用 Thread thread1 = new Thread( new MyThread(), "SyncThread1"); Thread thread2 = new Thread( new MyThread(), "SyncThread2"); thread1.start(); thread2.start();
修饰一个类
-
用于修饰静态方法,作用于该类的所有对象,在多线程情况下,无论线程持有该类的那个对象,在同一时刻只有一个线程可以访问,其他线程无论是否是有同一对象,都必须处于等待状态
public class MyThread implements Runnable { private static int count; public MyThread() { count = 0; } @Override public void run() { method(); } public static void method() { synchronized (MyThread.class) { for (int i = 0; i < 5; i++) { try { System.out.println(Thread.currentThread().getName() + ":" + (count++)); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } } } //调用 Thread thread1 = new Thread( new MyThread(), "SyncThread1"); Thread thread2 = new Thread( new MyThread(), "SyncThread2"); thread1.start(); thread2.start();
死锁
-
造成的原因
- 线程1/2/3分别持有A/B/C对象,现在线程1想获取B对象,线程2想获取C对象,线程3想获取A对象,但是三个对象分别被三个线程持有,随意导致三个线程不能释放也不能获取,从而导致死锁
-
解决方案
-
减小了锁定的范围
-
调整申请锁的顺序
-