在多个线程使用同一个资源的时候,有可能存在一个资源被一个线程占有,但一系列操做(原子操做:不可再分割的操做)并未执行完成,执行过程当中的资源被其余线程拿去用了。java
在一个线程执行原子操做时,其余线程不能占有资源安全
同步锁在括号中,是线程共同享有的资源ide
@Override public void run() { for (int i = 0; i < 50; i++) { String name = Thread.currentThread().getName(); synchronized (this) {//同步锁,线程共同享有的资源,这里的this是指Apple对象 if (num > 0) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(name + "吃了第" + num-- + "个苹果"); } } } }
使用synchronized来修饰方法,对于非静态方法,同步锁是this;对于非静态方法,同步锁是当前方法所在类的字节码对象 类名.class性能
@Override public void run() { for (int i = 0; i < 50; i++) { test(); } } private synchronized void test() { String name = Thread.currentThread().getName(); if (num > 0) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(name + "吃了第" + num-- + "个苹果"); } }
synchronized采用了自动加锁和释放锁的机制,手动加锁的方法更加透明,功能更增强大ui
package java_study; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; class Apple3 implements Runnable { public int num = 50; //1.因为 Lock 是一个接口,使用其实现类 ReentrantLock 得到一个锁对象 private final Lock lock = new ReentrantLock(); @Override public void run() { for (int i = 0; i < 50; i++) { eat(); } } private void eat() { //2.在方法的开始加锁吗,须要使用try-finally保证释放锁的进行 lock.lock(); try { if (num > 0) { Thread.sleep(10); String name = Thread.currentThread().getName(); System.out.println(name + "吃了第" + num-- + "个苹果"); } } catch (InterruptedException e) { e.printStackTrace(); } finally { //3.释放锁 lock.unlock(); } } } public class ClockDemo { public static void main(String[] args) { Apple3 a = new Apple3(); new Thread(a, "A").start(); new Thread(a, "B").start(); new Thread(a, "C").start(); } }