赵雅智_java 多线程(2)之线程同步

来源:互联网 发布:缤纷de饰界淘宝 编辑:程序博客网 时间:2024/06/05 10:14

线程同步

package com.csdn;class Tickets{public int tickets;public Tickets(){tickets = 10;}}public class SaleTicket {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubTickets t = new Tickets();Ticket st1 = new Ticket(t,"小王");Ticket st2 = new Ticket(t,"小张");}}class Ticket extends Thread {Tickets t;String name;public Ticket(Tickets t,String name){this.t = t;this.name = name;start();}@Overridepublic void run() {// TODO Auto-generated method stubfor(int i=0; i<5; i++){System.out.println(name+"抢到了第"+t.tickets+"票号");t.tickets--;try {Thread.sleep(20);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}

package com.csdn;public class SaleTickets {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubSaleTicke st = new SaleTicke();Thread t1 = new Thread(st);Thread t2 = new Thread(st);t1.start();t2.start();}}class SaleTicke implements Runnable{private int tickets = 20;@Overridepublic void run() {// TODO Auto-generated method stubwhile(true){if(tickets>0){try {Thread.sleep(20);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println(Thread.currentThread().getName()+"......"+tickets--);}}}}



为什么需要“线程同步” ??

线程间共享代码和数据可以节省系统开销,提高程序运行效率,但同时也导致了数据的“访问冲突”问题

如何实现线程间的有机交互、并确保共享资源在某些关键时段只能被一个线程访问,即所谓的“线程同步”(Synchronization)就变得至关重要。

临界资源: 多个线程间共享的数据称为临界资源(Critical Resource),

由于是线程调度器负责线程的调度,程序员无法精确控制多线程的交替顺序。因此,多线程对临界资源的访问有时会导致数据的不一致行。


互斥锁

每个对象都对应于一个可称为“互斥锁”的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。

Java对象默认是可以被多个线程共用的,只是在需要时才启动“互斥锁”机制,成为专用对象。

关键字synchronized用来与对象的互斥锁联系

当某个对象用synchronized修饰时,表明该对象已启动“互斥锁”机制,在任一时刻只能由一个线程访问,即使该线程出现堵塞,该对象的被锁定状态也不会解除,其他线程任不能访问该对象。

synchronized关键字的使用方式有两种:
1.同步代码块
synchronized(对象){

需要同步的代码
}


2.同步函数: 使用的锁是this

public synchronized void show(){

}

 

  1. 用在对象前面限制一段代码的执行(同步代码块)
    package com.csdn;class Tickets1{public int tickets;public Tickets1(){tickets = 10;}}public class TestMulThread2{     /** * @param args */public static void main(String[] args) {Tickets1 t = new Tickets1();Ticket1 st1 = new Ticket1(t,"小王");Ticket1 st2 = new Ticket1(t,"小张");}}class Ticket1 extends Thread {static String st1 ="aaa";Tickets1 t;String name;public Ticket1(Tickets1 t,String name){this.t = t;this.name = name;start();}public synchronized void show(){//同步代码块System.out.println(name+"抢到了第"+t.tickets+"票号");t.tickets--;}@Overridepublic void run() {for(int i=0; i<5; i++){synchronized(st1){System.out.println(name+"抢到了第"+t.tickets+"票号");t.tickets--;}//show();try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}

     
    package com.csdn;public class SaleTicketsSy {public static void main(String[] args) {// TODO Auto-generated method stubSaleTicketsy st = new SaleTicketsy();Thread t1 = new Thread(st);Thread t2 = new Thread(st);t1.start();t2.start();}}class SaleTicketsy implements Runnable{private int tickets = 100;@Overridepublic void run() {// TODO Auto-generated method stubObject obj = new Object();while(true){synchronized(obj){//同步代码块if(tickets>0){try {Thread.sleep(20);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println(Thread.currentThread().getName()+"......"+tickets--);}}}}}

  2. 用在方法声明中,表示整个方法为同步方法
    package com.csdn;public class TestMulThread {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubTickets2 t = new Tickets2();TicketsThread d1 = new TicketsThread(t,"Jam");TicketsThread d2 = new TicketsThread(t,"Jack");}}class Tickets2{public int tickets;public Tickets2(){tickets = 10;}public synchronized void action(String name){//锁方法System.out.println(name+"抢到了第"+tickets+"票号");tickets--;}}class TicketsThread extends Thread{Tickets2 t;String name;public TicketsThread(Tickets2 t, String name){this.t = t;this.name = name;start();}public void run(){for(int i=0;i<5;i++){t.action(name);try {Thread.sleep(20);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}

    package com.csdn;public class SaleTicketsSy2 {public static void main(String[] args) {// TODO Auto-generated method stubSaleTicketsy2 st = new SaleTicketsy2();Thread t1 = new Thread(st);Thread t2 = new Thread(st);t1.start();t2.start();}}class SaleTicketsy2 implements Runnable{private int tickets = 100;@Overridepublic void run() {// TODO Auto-generated method stubwhile(true){show();}}public synchronized void show(){//锁方法if(tickets>0){try {Thread.sleep(20);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println(Thread.currentThread().getName()+"......"+tickets--);}}}

同步好处:决了线程安全问题

同步弊端:降低了运行效率(判断锁是较为消耗资源的)

死锁:同步嵌套,容易出现死锁

死锁 两个线程A、B用到同一个对象s(s为共享资源),且线程A在执行中要用到B运行后所创造的条件。在这种前提下A先开始运行,进入同步块后,对象s被锁定,接着线程A因等待B运行结束而进入阻塞状态,于是B开始运行,但因无法访问对象s,线程B也进入阻塞状态,等待s被线程A解锁。最终的结果:两个线程互相等待,都无法运行。

package com.csdn;public class DeadLock {/** * @param args */public static void main(String[] args) {Demo6 d1=new Demo6(true);Demo6 d2=new Demo6(false);Thread t1=new Thread(d1);Thread t2=new Thread(d2);t1.start();t2.start();}}class MyLock{static MyLock lock1=new MyLock();static MyLock lock2=new MyLock();}class Demo6 implements Runnable{//String str1=new String("aaa");//String str2=new String("bbb");private boolean flag;public Demo6(boolean flag){this.flag=flag;}@Overridepublic void run() {if(flag){synchronized(MyLock.lock1){System.out.println(Thread.currentThread().getName()+"...if...str1");synchronized(MyLock.lock2){System.out.println(Thread.currentThread().getName()+"...if...str2");}}}else{         synchronized(MyLock.lock2){         System.out.println(Thread.currentThread().getName()+"...else...str2");         synchronized(MyLock.lock1){System.out.println(Thread.currentThread().getName()+"...else...str1");}}}}}



分析:这是线程死锁的典型表现,两个以上线程并发运行,他们均因其他线程锁定了自己运行所需资源而陷入阻塞状态,同时自己也锁定了其他线程所需资源。

 

单例类

懒汉式

class Single{
   private static Single s=null;
   private Single(){}
   public static Single getInstance(){
       if(s==null)
          synchronized(Singel。class){
             if(s==null)
               s=new Single();
         }

         return s;

}


class Single{
   private static Single s=null;
   private Single(){}
   public static synchronized Single getInstance(){
       
       
          if(s==null)
              s=new Single();
       

         return s;}
Single.getInstance();


饿汉式


class Single{
   private static Single s=new Single();
   private Single(){}
   public static Single getInstance(){
         return s;


}

}

 

原创粉丝点击