同步代码块
Java多线程支持引入了同步监视器来解决多线程安全,同步监视器的常用方法就是同步代码块。
Synchronized(obj){
//...同步代码块
}
括号中的obj就是同步监视器:上面的语句表示:线程开始执行同步代码块之前,必须先获得对同步监视器的锁定。这就意味着任何时刻只能有一条线程可以获得对同步监视器的锁定,当同步代码块执行结束后,该线程自然释放了对该同步监视器的锁定。
虽然java中对同步监视器使用的对象没有任何要求,但根据同步监视器的目的:阻止两条线程对同一个共享资源进行并发访问。所以一般将可能被并发访问的共享资源充当同步监视器。
public void run() {
synchronized (accout) {
// 账户余额大于取款金额时
if (accout.getBalance() >= drawAmount) {
// 取款成功
System.out
.println(Thread.currentThread().getName() + accout.getAccoutName() + "取款成功:吐出钞票:" + drawAmount);
// 修改余额
accout.setBalance(accout.getBalance() - drawAmount);
System.out.println("当前余额为:" + accout.getBalance());
}
// 账户金额不够时
else {
System.out.println("账户金额不够,您的余额只有" + accout.getBalance());
}
}
}
同步方法
synchronized可以修饰方法,代码块。不能修饰属性和构造方法.
除了同步代码块外还可以使用synchronized关键字来修饰方法,那么这个修饰过的方法称为同步方法。对于同步方法来说,无需显式指定同步监视器,同步方法的同步监视器是this,也就是该对象本身,也就是上面TestDraw中定义的Accout类型的acct。
public void run() {
draw();
}
public synchronized void draw() {
if (accout.getBalance() >= drawAmount) {
// 取款成功
System.out.println(Thread.currentThread().getName() + accout.getAccoutName() + "取款成功:吐出钞票:" + drawAmount);
// 修改余额
accout.setBalance(accout.getBalance() - drawAmount);
System.out.println("当前余额为:" + accout.getBalance());
}
// 账户金额不够时
else {
System.out.println("账户金额不够,您的余额只有" + accout.getBalance());
}
}