在多线程编程中,这种会被多个线程同时访问的资源叫做临界资源。
Synchronized关键字是一个修饰符,可以修饰方法或代码块。其作用是:对于同一个对象(不是一个类的不同对象),当多个线程都同时调用该方法或代码块时,必须一次执行,也就是说,如果两个或两个以上的线程同时执行该段代码,如果一个线程已经开始执行该段代码,则另外一个线程必须等待这个线程执行完这段代码才能开始执行。 多线程的同步提高了系统的安全问题 线程同步的两种表现形式: 1.同步代码块。 synchronzied(对象锁){ 需要被同步的代码。(哪些需要同步哪些不需要一定要分清) } 2.同步函数。 就是在函数上加了synchronzied关键字进行修饰。、 同步代码块可以使用任意对象作为锁。 同步函数使用的锁只有一个,就是this。 注意:static同步函数使用的锁是该函数所属类的对象。类名.class 售票系统中的线程同步方法: package com.hbsi; //模拟临界资源的类 class Tickets{ publicinttickets; public Tickets(){ tickets=10; } publicsynchronizedvoid action(String name){ System.out.println(name+"抢到了第"+tickets+"号票"); tickets--; } } //访问数据的线程 class TicketsThread extends Thread{ Tickets t; String name; public TicketsThread(Tickets t,String name){ this.t=t; this.name=name; start(); } @Override publicvoid run() { try { for(int i=0;i<5;i++){ t.action(name); Thread.sleep(20); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } //测试多线程访问时的问题 publicclass TestMulThread2{ publicstaticvoid main(String[] args) { // TODO Auto-generated method stub Tickets t=new Tickets(); TicketsThread d1=new TicketsThread(t,"小王"); TicketsThread d2=new TicketsThread(t,"小张"); } } 运行结果: 小王抢到了第10号票 小张抢到了第9号票 小王抢到了第8号票 小张抢到了第7号票 小王抢到了第6号票 小张抢到了第5号票 小王抢到了第4号票 小张抢到了第3号票 小王抢到了第2号票 小张抢到了第1号票 售票系统中的线程同步代码块: package com.hbsi; publicclass ticket1 implements Runnable{ privateintticket=100; @Override publicvoid run() { // TODO Auto-generated method stub //Object obj=new Object(); while(true){ synchronized(this){ if(ticket>0){ try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"..."+ticket--); }else{ break; } } } } publicstaticvoid main(String[] args) { // TODO Auto-generated method stub ticket1 t=new ticket1(); Thread td1=new Thread(t); Thread td2=new Thread(t); td1.start(); td2.start(); } } 单例类懒汉式的线程同步: Public class Single{ privatestatic Single s = null; privateSingle(){} publicstatic Single getInstance(){ if(s==null){ synchronized(Single.class) { if(s==null) s= new Single(); } } return s; } } 线程同步以后,懒汉式的安全性就进一步的提高。 线程的死锁: 产生死锁的原因主要是 因为系统资源不足。 进程运行推进的顺序不合适。 资源分配不当等。 如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。 产生死锁的四个必要条件 互斥条件:一个资源每次只能被一个进程使用。 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。 这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。