1)同步代码块
定义:使用同步监视器来解决线程冲突的问题,实现该同步监视器的通用方法。
2)语法结构
- package com.example.bankthread;
- public class BankAccountDrawThread extends Thread {
- private BankAccount bankAccount;
- private double drawAmount;
-
- public BankAccountDrawThread(String name,BankAccount account,double drawAccount) {
- // TODO Auto-generated constructor stub
- super(name);
- this.bankAccount = account;
- this.drawAmount = drawAccount;
- }
-
- @Override
- public void run() {
- // TODO Auto-generated method stub
- /*
- * 使用bankAccount作为同步监视器,
- * 任何线程在进入同步代码块之前,都会先获取对bankAccount的锁定,
- * 此时,其他线程无法获得锁,也就无法修改它
- *
- */
- synchronized(bankAccount)
- {
- if(bankAccount.getBalance()>= drawAmount)
- {
- System.out.println(getName()+"取钱成功,出钞:"+drawAmount);
- /* try {
- Thread.sleep(1);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }*/
- bankAccount.setBalance(bankAccount.getBalance()-drawAmount);
- System.out.println("\t余额为:"+bankAccount.getBalance());
- }
- else
- {
- System.out.println(getName()+"取钱失败!余额不足!");
- }
- }
- }
-
- public static void main(String[] args) {
- BankAccount bankAccount = new BankAccount("1234567", 10000);
-
- new BankAccountDrawThread("甲", bankAccount, 8000).start();
- new BankAccountDrawThread("乙", bankAccount, 8000).start();
- }
- }
复制代码
3)所代表含义
线程开始执行同步代码块之前,必须先获得对同步监视器的锁定。
4)逻辑思想
加锁---》修改---》释放锁。
5)同步方法:
使用synchronized关键字来修饰某个方法
6)语法结构
- package com.example.bankthread;
- public class AccountDrawThread extends Thread {
-
- private Account account;
- private double drawAmount;
-
- //设置线程的名字,对应的账户及所需取得钱
- public AccountDrawThread(String name,Account account,double drawAmount) {
- super(name);//调用父类Thread类中的方法,为线程指定线程名称
- this.account = account;
- this.drawAmount = drawAmount;
- }
-
- @Override
- public void run() {
- // TODO Auto-generated method stub
- /*
- * 由于draw()方法,使用synchronized修饰,故此时同步监视器是this,
- * 故多线程在调用该accoun时,必须先对account对象加锁
- */
- account.draw(drawAmount);
- }
- }
复制代码
7)对于synchronized修饰的实例方法而言,无须显示的指定同步监视器,其监视器是this引用指代的对象。
8)线程安全的类的特征:
A,该类的对象可以被多个线程安全地访问;
B,每个线程调用该对象的任意方法后,都将得到正确的结果;
C,每个线程调用该对象的任意方法后,该对象依然保持合理状态。
9)为了减少为实现线程安全而带来的运行效率的损失,线程通常采用如下策略:
A,不要对线程安全类的所有方法进行同步,只对那些会改变竞争资源(共享资源)的方法进行同步控制;
B,如果可变类有两种运行环境:单线程和多线程,则应该为该可变类通过两个版本——线程安全版本及线程不安全版本。单线程时,使用线程不安全版本;多线程时,使用线程安全版本。
10)同步监视器的锁定释放
释放情形如下:
A,当前线程的同步方法、同步代码块执行结束;
B,当前线程的同步方法、同步代码块遇到了break或者continue等终止运行;
C,当前线程的同步方法、同步代码块出现了未处理的Error或Exception,导致了代码块或方法异常结束时;
D,当前线程执行同步代码块或者同步方法时,程序执行同步监视器对象的wait()方法,当前线程暂停。
不会释放的情形:
A,线程执行同步代码块或者同步方法时,程序调用Thread.sleep()、Thread.yield()方法来暂停当前线程的执行,当前线程不会释放同步监视器;
B,线程执行同步代码块是,其他线程调用了该线程的suspend()方法,将线程挂起,该线程不会释放同步监视器。
|
|