初识JAVA---线程的同步,对象互斥锁(解决不确定性)、死锁(9)

先看下面例子  再说为什么要线程的同步

class TestThreadCount{
	static int cnt=0;
	public static void main(String[] args)
	{
		final int NUM=5000;
		Thread[] threads =new Thread[NUM];
		for (int i=0;i<NUM;i++) {
			threads[i]=new Thread() {
				public void run(){
					cnt++;
					try {Thread.sleep(1);}catch(InterruptedException ex) {}
				}
			};
		}
		for(int i=0;i<NUM;i++)threads[i].start();
		
		try {Thread.sleep(1);}catch(InterruptedException ex) {}
		System.out.printf("%d %b\n",cnt,cnt=NUM);
	}
}

先阅读这个程序   创建了5000个线程, for循环中   run  执行线程执行之后运行的代码,每次计数1  所以当线程行完毕之后  cnt应该是5000

4998 false   4999 false   也有时候是5000     为什么会这样

简单的说   线程之间是共享内存的  当一个线程执行的时候  例如 cnt=23   它还没来得及++    马上操作系统调度第二个线程执行  这样就导致了有时候数字不对   这时候需要用到线程间的同步

java引入了对象互斥锁概念,来保证共享数据操作的完整性

每个对象都对应于一个监视器,它上面一个称为“互斥锁”的标记/状态,这个标记用来保证在任一时刻,只能有一个线程访问该对象。          

简答的说就是它上面有一个状态,这个状态的每一个变量都有这个状态,同时,每一时刻最多被某一个线程使用。。这个可以比喻成商场买衣服时候的试衣间,换衣服,这个时刻只能 有一个人进去,别人就不能用了,除非这个人把这个标记给释放掉。

在线程中就是只能有一个线程同时拥有这个锁  /状态

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

synchronized用法

代码片段  

synchronized(对象){...}相当于对象加锁  别的线程进不来  这段代码有人叫临界代码,进了这个临界区,别人是进不来的

对某个方法:

synchronized放在方法声明中

public synchronized void push(char c){...}

相当于对synchronized(this)表示整个方法为同步方法 

import java.util.Date;

class SynCounter2{
	public static void main(String[] args) {
		Num num=new Num();
		Thread counter1= new Counter(num);
		Thread counter2= new Counter(num);
		Thread counter3= new Counter(num);
		try {
			Thread.sleep(100);
		}catch(InterruptedException e) {}
	}
}

class Num{
	private int x=0;
	private int y=0;
	synchronized void increase() {//它执行完之后  另一个线程才可以过来
		x++;
		y++;
	}
	synchronized boolean testEquals() {
		boolean ok=(x==y);
		System.out.println(x+","+y+":"+ok);
		return ok;
	}
}

class Counter extends Thread{
	 private Num num;
	 private boolean stop = false;

	 public void stopCounter(){
	 stop=true; 
	 }

	 Counter(Num num){
	 this.num=num;
	 this.start();
	 }
	 
	 public void run(){
	 //while(!stop){
	 //num.increase();
	 //}
		 for(int i=0;i<10;i++) {
		   num.increase();
		 }
		 num.testEquals();
		 
	 }
	 
	}

结果

10,10:true
20,20:true
30,30:true  也即 线程之间没有串扰。但有时候会出现21,21;true 的情况这个不明白为什么(以后解决把)

用wait()方法可以释放对象锁

用notify()或notifyAll()可以让等待得一个或所有线程进如就绪状态

Java里面可以将wait notify放在synchronized里  

     JAVA中 synchronized代码被执行期间,线程调用对象得wait()方法,会释放对象锁标志,然后进入等待状态

     notify()方法 也是这样   表示按当前操作做完了  别的线程可以来工作了

线程的死锁  彼此互相等待

第一个对象启动 上锁  第二个对象启动 上锁   调用方法的时候,第一个对象与第二个对象合作  但是得等待第二个对象得锁打开 这时候没有相应得操作    与此类似  第二个对象和第一个对象合作,也在等第二个对象开锁 这时候就死锁了

class Worker{
	int id;
	public Worker(int id) {this.id=id;}
	synchronized void doTaskWithCopperator(Worker other) {
		try {Thread.sleep(500);}catch(Exception e) {}
		synchronized(other) {
			System.out.println("dong"+id);
		}
	}
}

class DeadLockDemo{
	public static void main(String[] args) {
		Worker w1=new Worker(1);
		Worker w2=new Worker(2);
		Thread td1=new Thread(()-> {w2.doTaskWithCopperator(w1);});
		Thread td2=new Thread(()-> {w2.doTaskWithCopperator(w1);});
		td1.start();
		td2.start();
	}
}
发布了103 篇原创文章 · 获赞 9 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_39653453/article/details/103684606