Java基础总结----多线程安全性&同步

来源:互联网 发布:mysql where 优先级 编辑:程序博客网 时间:2024/05/16 16:19
Java对于多线程的安全问题提供了专业的解决方式。

同步代码块

synchronized(对象)
{
     需要被同步的代码

}
对象如同锁。持有锁的线程可以在同步中执行。
没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。

火车上的卫生间---经典。

同步的前提:
1,必须要有两个或者两个以上的线程。
2,必须是多个线程使用同一个锁。

必须保证同步中只能有一个线程在运行。

好处:解决了多线程的安全问题。

弊端:多个线程需要判断锁,较为消耗资源,

同步函数

在函数上加上synchronized修饰符即可。
函数需要被对象调用。那么函数都有一个所属对象引用。就是this。
所以同步函数使用的锁是this


classTicketimplementsRunnable {
     privatestaticinttick= 100;
     publicvoidrun() {
           while(tick> 1) {
                        show();
            }
      }

     publicsynchronizedvoidshow() {
           try{
                  Thread.sleep(10);
            }catch(Exception e) {
            }
           // synchronized (Ticket.class) {
            System.out.println(Thread.currentThread().getName() + ".... " + tick--);
           //tick--;
           // }
      }
}

publicclassTs {
     publicstaticvoidmain(String[] args) {
            Ticket a =newTicket();// 一个实例
           newThread(a).start();
           newThread(a).start();
      }
}

需求:
银行有一个金库。
有两个储户分别存300员,每次存100,存3次

classBank
{
     privateintsum;
     //Objectobj= new Object();
     publicsynchronizedvoidadd(intn)
      {
           //synchronized(obj)
           //{
                 sum=sum+ n;
                 try{Thread.sleep(10);}catch(Exception e){}
                  System.out.println("sum="+sum);
           //}
      }
}

classCusimplementsRunnable
{
     privateBankb=newBank();
     publicvoidrun()
      {          
           for(intx=0; x<3; x++)
            {
                 b.add(100);
            }
      }
}


class  BankDemo
{
     publicstaticvoidmain(String[] args)
      {
            Cus c =newCus();
            Thread t1 =newThread(c);
            Thread t2 =newThread(c);
            t1.start();
            t2.start();
     }
}

如果同步函数被静态修饰

注意:对于static的同步函数,使用的锁不是this。是 类名.class 是该类的字节码文件对象。
     涉及到了单例设计模式的懒汉式

通过验证,发现不在是this。因为静态方法中也不可以定义this。

静态进内存是,内存中没有本类对象,但是一定有该类对应的字节码文件对象。
类名.class  该对象的类型是Class

静态的同步方法,使用的锁是该方法所在类的字节码文件对象。 类名.class

     publicvoidrun()
      {
           if(flag)
            {
                 while(true)
                  {
                       synchronized(Ticket.class)
                        {
                             if(tick>0)
                              {
                                   try{Thread.sleep(10);}catch(Exception e){}
                                    System.out.println(Thread.currentThread().getName()+"....code : "+tick--);
                              }
                        }
                  }
            }
           else
                 while(true)
                       show();
      }
     publicstaticsynchronizedvoidshow()
      {
           if(tick>0)
            {
                 try{Thread.sleep(10);}catch(Exception e){}
                  System.out.println(Thread.currentThread().getName()+"....show.... : "+tick--);
            }
      }
}

死锁。
同步中嵌套同步

死锁代码一定会写。但开发时一定注意避免

classMyLock
{
     staticObjectlocka=newObject();
     staticObjectlockb=newObject();
}
while(true)
{
     synchronized(MyLock.lockb)
      {
            System.out.println(Thread.currentThread().getName()+"..else lockb");
           synchronized(MyLock.locka)
            {
                  System.out.println(Thread.currentThread().getName()+".....else locka");
            }
      }
}
0 0