在大多数实际多线程应用中两个或者两个以上的线程需要共享同一对数据存取,那两个线程操作同一个对象,并且两个线程都调用修改了象数据的方法,这种情况就会造成线程不安全,需要实现线程同步,使对象变的安全,线程同步实际上是一个等待的机制,通过队列和锁进行排队等待,多个线程需要访问同一个对象的时候则进入这个对象的等待队列,等待前一个对象使用完毕下一个线程在使用.
队列和锁同步方法及同步块队列:多个线程需要访问同一个对象的时候则进入这个对象的等待队列
锁:第一个访问对象的线程会获得一把锁,线程运行完毕之后才会把锁给下一个线程
java处理这些不安全的线程提供了关键字synchronized来使线程进行同步,有两种使用方式
同步方法基本语法:
public synchronized void Test(){}
synchronized方法控制对对象的访问,每个对象对应这一把锁,每个synchronized方法都必须获得调用该方法对象的锁才能执行,否则线程会堵塞,方法一旦执行就独占该锁,直到方法返回才释放锁,后面被堵塞的线程才能获得锁继续执行.
注意:虽然安全性提高但是效率会大大降低
同步块的基本语法:
public void Test(){ synchronized(Obj){ //需要同步的代码 }}
案例obj又被称为同步监视器obj可以是任何对象,但是推荐使用共享资源作为同步监视器同步方法中无需指定同步监视器,因为同步方法的同步监视器就是this或者是class
不安全买票
public class test2 { static class Test implements Runnable { //票数 int ps = 10; //判断是否还有票 boolean pd = true; @Override public void run() { while (pd) { test(); } } public void test() { if (ps <= 0) { pd = false; return; } System.out.println(Thread.currentThread().getName() + "获得了第" + ps-- + "张票"); } } public static void main(String[] args) { Test test = new Test(); new Thread(test, "小明").start(); new Thread(test, "小美").start(); new Thread(test, "大美").start(); }}
使用同步方法安全买票:
public class test2 { static class Test implements Runnable { //票数 int ps = 10; //判断是否还有票 boolean pd = true; @Override public void run() { while (pd) { //这个睡眠是模拟延时,提供发生率,不然小明抢的太块了 try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } test(); } } public synchronized void test() { if (ps <= 0) { pd = false; return; } System.out.println(Thread.currentThread().getName() + "获得了第" + ps-- + "张票"); } } public static void main(String[] args) { Test test = new Test(); new Thread(test, "小明").start(); new Thread(test, "小美").start(); new Thread(test, "大美").start(); }}
模拟不安全取钱
public class test3 { public static void main(String[] args) { User user=new User(1000,"银行卡"); new Thread(new Bank(user,1000),"我").start(); new Thread(new Bank(user,1000),"妻子").start(); }}//用户class User { int money; String name; public User(int money, String name) { this.money = money; this.name = name; }}//银行class Bank implements Runnable{ //用户 User user; //取出的前 int getMoney; public Bank(User user, int getMoney) { this.user = user; this.getMoney = getMoney; } public void run() { if (getMoney > user.money) { System.out.println("余额不足..."); return; } //模拟延时 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } user.money = user.money - getMoney; System.out.println(Thread.currentThread().getName()+"取出"+getMoney+",剩余余额"+user.money); }}
使用同步块安全买票
public class test3 { public static void main(String[] args) { User user=new User(1000,"银行卡"); new Thread(new Bank(user,1000),"我").start(); new Thread(new Bank(user,1000),"妻子").start(); }}//用户class User { int money; String name; public User(int money, String name) { this.money = money; this.name = name; }}//银行class Bank implements Runnable{ //用户 User user; //取出的前 int getMoney; public Bank(User user, int getMoney) { this.user = user; this.getMoney = getMoney; } public void run() { //注意这里修改谁就监视谁,这里修改的是账户 synchronized (user){ if (getMoney > user.money) { System.out.println("余额不足..."); return; } //模拟延时 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } user.money = user.money - getMoney; System.out.println(Thread.currentThread().getName()+"取出"+getMoney+",剩余余额"+user.money); } }}