关于线程的同步,可以使用synchronized关键字,或者是使用JDK 5中提供的java.util.concurrent.lock包中的Lock对象。本文探讨synchronized关键字。
synchronized关键字可以修饰方法,可以修饰代码块,但不能修饰构造器、属性等。
package com.clzhang.sample.thread; public class SyncThread1 implements Runnable { private Integer key = 0; @Override public void run() { // key是Integer对象(注意不是int,因为int不是对象) // 线程进入下面同步代码之前,需要先获取key的锁。 // 需要结果是key实现自增长,如果没有同步块,则可能会出现重复key值的现象 synchronized (key) { key++; System.out.println(Thread.currentThread().getName() + ":" + key); try { Thread.sleep(100); } catch (InterruptedException e) { } } } public static void main(String[] args) { SyncThread1 st = new SyncThread1(); for(int i=0; i<10; i++) { new Thread(st, "Thread" + i).start(); } } }
输出:
Thread1:2
Thread3:3
Thread5:4
Thread7:5
Thread0:2
Thread2:7
Thread9:6
Thread4:8
Thread6:9
Thread8:10
同步方法分静态和非静态两种。静态方法则一定会同步,非静态方法需在单例模式才生效,推荐用静态方法(不用担心是否单例)。
package com.clzhang.sample.thread; // 如果是同步方法,则分静态和非静态两种。 // 静态方法则一定会同步,非静态方法需在单例模式才生效,推荐用静态方法(不用担心是否单例)。 public class SyncThread2 implements Runnable { private Integer key = 0; // 此示范为非静态方法同步 public synchronized Integer getKey() { key++; return key; } @Override public void run() { System.out.println(Thread.currentThread().getName() + ":" + getKey()); try { Thread.sleep(10); } catch (InterruptedException e) { } } public static void main(String[] args) { // 非静态方法同步,需要启动单例模式 SyncThread2 st = new SyncThread2(); for (int i = 0; i < 10; i++) { new Thread(st, "Thread" + i).start(); } } }
输出:
Thread0:1
Thread1:3
Thread2:2
Thread3:5
Thread5:6
Thread7:7
Thread9:8
Thread6:9
Thread8:10
Thread4:4
package com.clzhang.sample.thread; // 如果是同步方法,则分静态和非静态两种。 // 静态方法则一定会同步,非静态方法需在单例模式才生效,推荐用静态方法(不用担心是否单例)。 public class SyncThread3 implements Runnable { private static Integer key = 0; // 此示范为静态方法同步 public synchronized static Integer getKey() { key++; return key; } @Override public void run() { System.out.println(Thread.currentThread().getName() + ":" + getKey()); try { Thread.sleep(10); } catch (InterruptedException e) { } } public static void main(String[] args) { // 如果用静态方法实现同步,则可以生成对象的多个实例 for (int i = 0; i < 10; i++) { SyncThread3 st = new SyncThread3(); new Thread(st, "Thread" + i).start(); } } }
输出:
Thread3:3
Thread1:1
Thread0:2
Thread5:4
Thread7:5
Thread9:6
Thread2:7
Thread8:10
Thread6:9
Thread4:8
1、无论是同步代码块还是同步方法,必须获得对象锁才能够进入同步代码块或者同步方法进行操作。
2、如果采用方法级别的同步,对象锁为方法所在的对象;如果是静态同步方法,对象锁为方法所在的类(唯一)。
3、对于代码块,对象锁即指synchronized(object)中的object。