黑马程序员——多线程(synchronize_锁)


-----------android培训java培训、java学习型技术博客、期待与您交流!------------

实现Runnable方式创建线程

class Ticket implements Runnable
{
	private  int tick = 1;//所有线程共享
	boolean flog = true;
	public void run()
	{
		while(flog)
		{
			if(tick<=100)
			{
				System.out.println(Thread.currentThread().getName()+"sale :"+ tick++);
			}
			else
			{
				System.out.println("sale over");
				 flog = false;
			}
		}
	}
}

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);
		Thread t4 = new Thread(t);
		
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}

}

注意:Ticket没有定义为静态也能共享。


所有线程共享Ticket,出现安全问题。


public static void sleep(long millis)//暂停程序

问题的原因:

当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没执行完,

另一个线程参与近来执行。导致共享数据的错误。


解决办法:

对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中其他线程不可以参与执行。


Java对于多线程的安全问题提供了专业的解决方式。

就是同步代码快。


synchronized(对象)

需要被同步的代码


对象如同锁。持有锁的线程可以在同步中执行。

没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。


重点:

同步的前提:

1、必须要有两个或者两个以上的线程。

2、必须是多个线程使用同一个锁。


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


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


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


同步有两种表现形式:

1、同步代码块。

2、同步函数。


程序二:

/*
 * 需求:
 * 银行有一个金库。
 * 有两个储户分别存300元,每次存100,存3次。
 * 
 * 目的:该程序是否有安全问题,如何解决?
 * 
 * 如何找到问题:
 * 1、明确哪些代码是多线程运行代码。
 * 2、明确共享数据。
 * 3、明确多线程运行代码中哪些语句是操作共享数据。
 */



class Bank
{
	private int sum;
	//Object obj  = new Object();
	public synchronized void add(int n)
	{
		//synchronized(obj )
		//{
			sum = sum + n ;
			System.out.println("sum="+sum);
		//}
	}
}

class Cus implements Runnable
{
	private Bank b = new Bank();
	public void run()
	{
		for(int x = 0 ; x<3 ; x++)
		{
			b.add(100);
		}
	}
}



public class BankDemo 
{
	public static void main(String[] args) {
		Cus c = new Cus();
		
		Thread t1 = new Thread(c);
		Thread t2 = new Thread(c);
		
		t1.start();
		t2.start();

	}
}

同步函数用的是哪一个锁?

函数需要被对象调用。那么函数都有一个所属对象引用。就是this。

所以同步函数使用的锁是this。


通过程序验证同步函数中的锁是this。


使用两个线程来买票。

一个线程在同步代码快中。

一个线程在同步函数中。

都在执行买票动作。


静态同步函数的锁是Class对象

如果同步函数被静态修饰后,使用的锁不是this了。因为静态方法中也不可以定义this。

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

类名.class   该对象的类型是Class。

如类 Ticket中,有静态同步方法,则方法使用的锁是Ticket.class。


总结:

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


单例设计模式-懒汉式

/*
 * 单例设计模式。
 * 
 * 
 * 饿汉式。
 * 
 class Single
 {
 	private static final Single s = new Single();
 	private Single(){}//私有构造函数
 	public static Single getInstance()
 	{
 		return s;
 	}
 	
 }
 * 
 * 
 */
//懒汉式: 
//特点:实例的延时加载。
class Single
{
	private static  Single s = null;
	private Single(){}
	/*
	public static synchronized Single getInstance()
	{
		if(s==null)
		{
			s=new Single();
		}
		return s;
	}
	*/
	public static  Single getInstance()
	{
		if(s==null)//减少锁判断的速度
		{
			synchronized(Single.class)//锁为该类所属的字节码文件对象
			{
				if(s==null)
				{
					s=new Single();
				}
			}
			
		}
		return s;
	}
}

死锁:

同步中嵌套同步。

写一个死锁程序:

class Test extends Thread
{
	private boolean flag;
	Test(boolean flag)
	{
		this.flag = flag;
	}
	
	public void run()
	{
		if(flag)
		{
			synchronized(MyLock.locka)
			{
				System.out.println("if locka");
				synchronized(MyLock.lockb)
				{
					System.out.println("if lockb");
				}
			}
		}
		else
		{
			synchronized(MyLock.lockb)
			{
				System.out.println("eles lockb");
				synchronized(MyLock.locka)
				{
					System.out.println("else locka");
				}
			}
		}
	}
}

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

public class DeadLockTest {

	public static void main(String[] args) {
		Thread t1 = new Thread(new Test(true));
		Thread t2 = new Thread(new Test(false));
		t1.start();
		t2.start();
	}
}


-----------android培训java培训、java学习型技术博客、期待与您交流!------------



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值