一、各个线程是经过竞争CPU时间而得到运行机会的
二、各线程何时获得CPU时间,占用多久,是不可预测的
三、一个正在运行着的线程在什么地方被暂停是不肯定的多线程
为了解决上述问题,确保共享对象在同一时间只容许被一个线程访问,即线程同步,可使用synchronized和lock来实现。ide
一、修饰一个代码块,被修饰的代码块称为同步代码块,做用范围是大括号{}括起来的代码;
二、修饰一个方法,被修饰的方法称为同步方法,其做用范围是整个方法;
三、修饰一个静态方法,做用范围是整个静态方法;
例程(银行存取款)测试
package com.imooc.bank; public class Bank { private String account;//帐号 private int balance;//帐户余额 public Bank(String account,int balane){ this.account=account; this.balance=balane; } public String getAccount() { return account; } public void setAccount(String account) { this.account = account; } public int getBalance() { return balance; } public void setBalance(int balance) { this.balance = balance; } @Override public String toString() { return "Bank[帐号:"+account+",余额:"+balance+"]"; } //存款 public synchronized void saveAccount(){ //获取当前的帐户余额 int balance=getBalance(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //修改金额,存100元 balance+=100; //修改帐余额 setBalance(balance); //输出存款后的帐户余额 System.out.println("存款后的帐户余额为:"+balance); } public void drawAccount(){ synchronized (this){ //得到当前帐户余额 int balance=getBalance(); balance=balance-200; try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } setBalance(balance); System.out.println("取款后的帐户余额:"+balance); } } }
package com.imooc.bank; public class DrawAccount implements Runnable{ Bank bank; public DrawAccount(Bank bank){ this.bank=bank; } @Override public void run() { bank.drawAccount(); } }
package com.imooc.bank; public class SaveAccount implements Runnable{ Bank bank; public SaveAccount(Bank bank){ this.bank=bank; } @Override public void run() { bank.saveAccount(); } }
package com.imooc.bank; public class Test { public static void main(String[] args) { //建立帐户,给定余额为10000 Bank bank=new Bank("1001",1000); //建立线程对象 SaveAccount sa=new SaveAccount(bank); DrawAccount da=new DrawAccount(bank); Thread save=new Thread(sa); Thread draw=new Thread(da); save.start(); draw.start(); try { draw.join(); save.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(bank); } }
通过测试,当不加入synchronized实现线程同步时,存款取款的帐户余额会发生错误,
这里使用线程延时模拟了线程被打断的状况,当存款没彻底进行完时打断了此线程进行取款
此时取款后的余额不正确。
this
当加入了线程同步后,此问题获得了解决。
线程
一、synchroized同步的时候,其中一条线程用完会自动释放锁,而Lock须要手动释放,若是不手动释放,可能形成死锁
二、使用synchronized若是其中一个线程不释放锁,那么其余须要获取锁的线程会一直等待下取,直到使用完释放或者出现异常,
而Lock可使用响应中断或者使用规定等待时间的锁
三、synchronized没法得知是否获取到锁,而Lock能够作到
四、用ReadWriteLock能够提升多个线程进行读操做的笑了code
lock简单的使用方法对象
//建立lock对象 Lock lock=new ReentrantLock(); //手动加锁 lock.lock(); try{ // 处理 }catch(Exception ex){ // 捕获异常 }finally{ // 释放锁 lock.unlock(); }