java多线程编程(五)-线程同步
一:synchronized同步方法和synchronized同步代码块
1,sysnchronized修饰对象方法
public synchronized void excute()
a,被synchronized修饰的方法称为同步方法,同步方法所处的对象会被上同步锁,该方法未执行完成其它线程是无法调用执行同步方法的。
b,若对象中存在多个同步方法,当一个方法被某个线程调用执行时,其它线程不仅无法调用执行该同步方法,其它同步方法也无法被调用执行,因为带同步锁的是对象,不是方法。
2,sysnochronized修饰类方法
public synchronized static void excuteClass()
a,当一个方法同时被synchronized和static修饰时,个人称之为同步类方法。同步类方法有同步方法所有特性。
b,同步类方法是将方法所处的类对应的Class对象上锁,所以多个线程访问Class对象被上锁的类创建的不同对象的同步方法,也是相互影响的,必须执行完一个,另一个线程才能执行,因为上锁的是模板Class对象,而不是普通创建的对象。
3,sysnochronized代码块
sysnochronized(object){
//执行代码
.....
}
a,同步代码块是为object对象上同步锁,object可以为任何对象,所以也包括this关键字引用的对象。
b,方法中不是被synchronized代码块包裹的代码,是可以被多个线程同时访问的。
二:同步锁案例(取钱案例)
用两个线程调用同一个目标对象的取钱方法,如果取钱方法不加锁,则可能导致账户余额不同步或账户透支,不符合实际情况。
package com.thread.www; import java.math.BigDecimal; //银行存款 class Bank{ BigDecimal onlnbl = new BigDecimal(100L); public /*synchronized*/ BigDecimal getCash(BigDecimal tranam){ if(tranam.compareTo(onlnbl)>0){ return new BigDecimal(-1); } //休眠一段时间,放弃bank对象使用 try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } this.onlnbl = this.onlnbl.subtract(tranam); return this.onlnbl; } } //取钱线程 class PrimeRun6 implements Runnable{ Bank bank; public PrimeRun6(Bank bank) { this.bank = bank; } @Override public void run() { //打印剩余金额 System.out.println(Thread.currentThread().getName()+" onlnbl="+bank.getCash(new BigDecimal(90L))); } } //测试类 public class Test6线程同步 { public static void main(String[] args) { Bank bank = new Bank(); PrimeRun6 peRun = new PrimeRun6(bank); new Thread(peRun).start(); new Thread(peRun).start(); } } /** * 结果可能为10,10 或10,-80 或-80,-80* */
参考资料:http://www.cnblogs.com/mengdd/archive/2013/02/16/2913806.html