JAVA基础----同步锁

同步机制:
解决多线程安全问题
   
同步代码块
格式:
synchronized (锁对象) {
需要同步的代码
}




<span style="font-size:24px;">public void run() {
			
<span style="white-space:pre">	</span>int i = 1;	</span>
<span style="font-size:24px;">
</span>
<span style="font-size:24px;"><span style="white-space:pre">	</span>while(i<100){</span>
<span style="font-size:24px;"><span style="white-space:pre">	</span></span>
<span style="font-size:24px;">	<span style="white-space:pre">	</span>//需要是同一把锁才能起到作用	
	<span style="white-space:pre">	</span>synchronized (obj) {
				
		<span style="white-space:pre">	</span>//需要被同步的内容,也就是需要多线程并发访问的内容</span>
<span style="font-size:24px;"><span style="white-space:pre">			</span>System.out.println(i++);</span>
<span style="font-size:24px;"><span style="white-space:pre">		</span>}</span>

<span style="font-size:24px;"><span style="white-space:pre">	</span>}<span style="white-space:pre">	</span></span>
<span style="font-size:24px;">}</span>



同步方法
(普通同步方法)
(静态同步方法)
格式:
修饰符 synchronized 返回值类型 方法名(参数列表){....}
</pre><pre name="code" class="java">//需要被多线程并发访问的同步方法
public synchronized void method(){

<span style="white-space:pre">		</span>//方法内容<span style="font-family: Arial, Helvetica, sans-serif;">		</span>
}
<pre name="code" class="java">//需要被多线程并发访问的静态同步方法
public static synchronized void method(){
<span style="white-space:pre">	</span>
<span style="white-space:pre">		</span>//方法内容

}
/*
<span style="white-space:pre">	</span>它们的区别在于,所对象不同。
<span style="white-space:pre">		</span>普通同步方法的锁对象是  tish
<span style="white-space:pre">		</span>而静态同步方法的锁对象是   字节码文件对象:
<span style="white-space:pre">			</span>类名.class
<span style="white-space:pre">		</span>那用谁好呢?
<span style="white-space:pre">			</span>它们的区别是:<span style="white-space:pre">	</span>
<span style="white-space:pre">				</span>静态与非静态,用谁就要看用静态还是不用静态
*/<span style="white-space:pre">	</span>
 




注意:


同步代码块,如果有多个同步代码块,那么锁对象,要求一致
同步方法,同步方法的锁对象是谁?  this
同步方法,同步静态方法的锁对象是谁?  字节码文件对象, 类名.class






Lock锁: jdk1.5
void lock()获取锁。 

void unlock()释放锁。


//新锁的使用与老锁一样,但它需要手动的释放锁。

<span style="white-space:pre">		</span>int i=100;

<span style="white-space:pre">		</span>//创建锁对象
	<span style="white-space:pre">	</span>Lock lock=new ReentrantLock();

	
public void run(){
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>while (true){

<span style="white-space:pre">		</span>//加锁
	<span style="white-space:pre">	</span>lock.lock();

<span style="white-space:pre">		</span>//被同步的内容
		if (0<i){
		<span style="white-space:pre">	</span>System.out.println(--i);
				
			}
		
<span style="white-space:pre">		</span>//释放锁
		lock.unlock();
		}
	}





死锁:
是指两个或者两个以上的线程在执行的过程中,因争夺资源(锁对象)产生的一种互相等待现象,下面是一段死锁的代码:

public class ThreadList {
	public static void main(String[] args) {
		
		//创建两个多线程对象,并赋值
		DieThread die = new DieThread("帅哥", true);
		DieThread die1 = new DieThread("美女", false);
		
		//启动多线程
		die.start();
		die1.start();
	}
}


<pre name="code" class="html">public class DieThread extends Thread {

	// 定义变量,用于判断被执行的代码
	public boolean flag;

	// 定义线程名称
	public String name;

	// 创建锁对象
	public static Object obj = new Object();
	public static Object obj1 = new Object();

	// 用于赋值的构造方法
	DieThread(String name, boolean flag) {
		this.name = name;
		this.flag = flag;

	};

	// 重写run方法
	public void run() {

		// 判断标签
		if (flag) {

			// 重复执行同步代码
			while (true) {

				// 锁1
				synchronized (obj1) {

					System.out.println(getName() + "obj----obj");

					// 锁0
					synchronized (obj) {

						System.out.println(getName() + "obj1---obj1");
					}
				}
			}
		} else {

			// 重复执行同步代码
			while (true) {

				// 锁0
				synchronized (obj) {

					System.out.println(getName() + "obj---obj");

					// 锁1
					synchronized (obj1) {
						System.out.println(getName() + "obj1---obj1");

					}
				}
			}
		}
	}
}

/*

 
<span style="white-space:pre">	</span>死锁是因为:
<span style="white-space:pre">		</span>线程一拿到了锁1,正在判断锁0.
<span style="white-space:pre">		</span>而线程二拿到了锁0,正在判断锁1.
<span style="white-space:pre">	</span>因为同一个锁只能进入一个对象,所以线程一进不去已经存在对象的锁0,线程二也同理。但它们都有各自的任务,那就是解开下一个锁,所以它们都不会释放锁。
*/



等待唤醒机制:
等待:

wait(): 让当前的线程等待,释放锁对象,让其他线程获取锁对象与CPU执行权,


等待着其他线程 调用 notify()\notifyAll()来 唤醒


唤醒:

notify()\notifyAll() : 可以唤醒当前锁对象上面的等待的线程


notify(): 随机唤醒锁对象上面的其中一个等待的线程对象


notifyAll(): 唤醒锁对象上面的所有等待的线程对象


//多生产多消费问题,等待唤醒机制

class Resource
{
	private String name;
	private int count = 1;

	//定义标记。
	private boolean flag = false;
	
	//1,提供设置的方法。
	public synchronized void set(String name)  
	{

		while(flag)

<span style="white-space:pre">			</span>/*睡眠方法会抛出<code>terruptedException</code>异常
<span style="white-space:pre">			</span>  如果在当前线程等待通知之前或者正在等待通知时
<span style="white-space:pre">			</span>  ,任何线程中断了当前线程。在抛出此异常时,
<span style="white-space:pre">			</span>  当前线程的<em>中断状态</em> 被清除。
<span style="white-space:pre">			</span>*/
		try{this.wait();}catch(InterruptedException e){}

		//给成员变量赋值并加上编号。
		this.name = name + count;

		//编号自增。
		count++;

		//打印生产了哪个商品。
		System.out.println(Thread.currentThread().getName()+"......生产者...."+this.name);


		//将标记改为true。
		flag = true;

		//唤醒消费者。
		this.notifyAll();

	}
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>//消费方法
	public synchronized void out(){

	
		while(!flag)
			try{this.wait();}catch(InterruptedException e){}
		System.out.println(Thread.currentThread().getName()+"....消费者...."+this.name);

		//将标记该为false。

		flag = false;

		//唤醒生产者。
		this.notifyAll();
	}
}

//2,描述生产者。
class Producer implements Runnable
{
	private Resource r ;

	// 生产者一初始化就要有资源,需要将资源传递到构造函数中。
	Producer(Resource r)
	{
		this.r = r;
	}
	public void run()
	{
		while(true)
		{
			r.set("面包");
		}
	}
}

//3,描述消费者。
class Consumer implements Runnable
{
	private Resource r ;

	// 消费者一初始化就要有资源,需要将资源传递到构造函数中。
	Consumer(Resource r)
	{
		this.r = r;
	}
	public void run()
	{
		while(true)
		{
			r.out();
		}
	}
}




class ThreadDemo10
{
	public static void main(String[] args) 
	{
		//1,创建资源对象。
		Resource r = new Resource();

		//2,创建线程任务。
		Producer pro = new Producer(r);
		Consumer con = new Consumer(r);

		//3,创建线程。
		Thread t1 = new Thread(pro);
		Thread t2 = new Thread(pro);
		Thread t3 = new Thread(con);
		Thread t4 = new Thread(con);

		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}
}

感谢传智!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值