码迷,mamicode.com
首页 > 编程语言 > 详细

同步(解决多线程安全问题)

时间:2016-08-06 17:32:38      阅读:236      评论:0      收藏:0      [点我收藏+]

标签:

1.创建线程的两种方式。

  (1)继承Thread(该类就定义了一个功能,用于存储线程要运行的代码,该存储功能就是run方法也就是说Thread类中的run方法,用于存储线程要运行的代码。


  
(2)实现Runnable(Runable中只定义了一个抽象方法,public void run();)

    步骤:
    1,定义类实现Runable接口
    2,覆盖Runable接口中的run方法。
    将线程要运行的代码存放在该run方法中。
    3,通过Thread类建立线程对象。
    4,将Runable接口的子类对象作为实际参数传递给Thread类的构造函数。
      为什么要将Runable接口的子类对象传递给Thread类的构造函数。
      因为,自定义run方法所属的对象是Runable接口的子类对象。所以要让线程去指定 指定对象的run方法。就必须明确该run方法所属的对象。
    5,调用Thread类的start方法开启线程并调用Runable接口的子类的run方法。
      在Thread类中提供了public Thread(Runnable target)和public Thread(Runnable target,String name)两种构造方法


    两种方式的区别?

    继承Thread:线程代码存放在Thread子类run方法中
    实现Runable:线程代码存在接口的子类的run方法。
    Thread类也是Runnable的子类。也就是说,Thread和Runnable的子类都同时实现了Runnable接口,之后将Runnable的子类实例放到了Thread类之中。
    Thread类和Runnable接口使用上的区别,如果一个类继承Thread类,则不适合于多个线程共享资源,实现了Runnable接口,就可以方便地实现资源的共享。
 
2.多线程的运行出现了安全问题。
问题的原因:
当多条语句在操作同一个线程共享数据时,一个线程对多条语句执行了一部分,还没执行完,另一线程参与进来执行。导致共享数据的错误。
 
解决办法:
对多条操作共享数据的语句,只能让一个线程都执行完,再执行过程中,其他线程不可以参与运行。
 
java对于多线程的安全问题,提供了专业的解决方式,就是同步代码块。
 
同步代码块格式:
  synchronized(对象1){
      需要同步的代码
    }
这个里面的对象1就如同锁,持有锁的线程,可以在同步中执行需要同步的代码
没有持有锁的线程即使获得CPU的执行权,也进不去,因为没有获取锁。
 
同步的前提:
(1)必须要有两个或两个以上的线程。
(2)必须有多个线程并使用同一个锁
 
必须保证同步中只能有一个线程在运行。
 
同步的好处和弊端:
好处:解决了线程的安全问题。
弊端:同步外的多个线程都需要判断锁,(这些是无效判断)较为消耗资源。
package org.lxh.demo9.threaddemo;
class Ticket implements Runnable{
    private  int tick=5;
    public void run(){
        while (true){
            synchronized(this){  //this是一个锁。
                if (tick>0){
                try{
                    Thread.sleep(500);
                }
                catch(Exception e){

                }
                System.out.println(Thread.currentThread().getName()+"sale..."+tick--);
            }
        }
            }

} 

public class TicketDemo {

    public static void main(String[] args) {
        Ticket t=new Ticket();
        Thread t1=new Thread(t);//创建了一个线程
        Thread t2=new Thread(t);//创建了一个线程
        Thread t3=new Thread(t);//创建了一个线程
        t1.start();
        t2.start();
        t3.start();
    }

} 

3.死锁

 常见情景之一:同步的嵌套

class Test implements Runnable
{
	private boolean flag;
	Test(boolean flag)
	{
		this.flag = flag;
	}

	public void run()
	{
		
		if(flag)
		{
			while(true)
				synchronized(MyLock.locka)
				{
					System.out.println(Thread.currentThread().getName()+"..if   locka....");
					synchronized(MyLock.lockb)				{
						
						System.out.println(Thread.currentThread().getName()+"..if   lockb....");
					}
				}
		}
		else
		{
			while(true)			
				synchronized(MyLock.lockb)
				{
					System.out.println(Thread.currentThread().getName()+"..else  lockb....");
					synchronized(MyLock.locka)
					{
						System.out.println(Thread.currentThread().getName()+"..else   locka....");
					}
				}
		}

	}

}

class MyLock
{
	public static final Object locka = new Object();
	public static final Object lockb = new Object();
}

class DeadLockTest 
{
	public static void main(String[] args) 
	{
		Test a = new Test(true);
		Test b = new Test(false);

		Thread t1 = new Thread(a);
		Thread t2 = new Thread(b);
		t1.start();
		t2.start();
	}
}

  运行结果:Thread1..else lockb...

       Thread0..if locka...

可以看到线程1拿到了lockb锁,而线程0拿到了locka锁,之后就发生了死锁,因为线程1拿到lockb锁之后,还要想往下运行,需要拿到locka锁,而locka锁在线程0那里;线程0拿到locka锁,想往下执行,需要拿到locka锁,但是lockb锁在线程1那里。这样就形成了死锁。

 

同步(解决多线程安全问题)

标签:

原文地址:http://www.cnblogs.com/GumpYan/p/5744393.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!