`

黑马程序员--java基础复习--线程--同步与通信

 
阅读更多



 

 ---------------------- ASP.Net+Android+IO开发S.Net培训、期待与您交流! ---------------------

  单个线程操作资源的时候,是不会出现安全问题的,但是如果多个线程操作同一个资源的时候,因为CPU的使用权限是大家平等的,在任何时候都可能执行任意线程的任意语句(在不加锁的情况下),这就会产生线程的安全问题,比如下边代码

package thread;

public class TestThread {
	private static int count;

	int line = 5;

	public static void main(String[] args) {
		TestThread tt = new TestThread();
		tt.startThread();
		tt.startThread();
	}

	class CountThread implements Runnable {
		public void run() {

			while (count < 25) {
				//synchronized (TestThread.class) {
					//if(count < 25){
						count++;
						System.out.print(Thread.currentThread().getName() + "--" + count + "\t");
						line--;
						if (line == 0) {
							System.out.println();
							line = 5;
						}
					}					
				//}				
			//}
		}
	}
	
	public void startThread() {
		new Thread(new CountThread()).start();
	}
}

 

 运行结果为:

 Thread-0--1 Thread-0--3 Thread-0--4 Thread-0--5 Thread-0--6 
Thread-0--7 Thread-0--8 Thread-0--9 Thread-0--10 Thread-1--2 
Thread-1--12 Thread-1--13 Thread-1--14 Thread-1--15 Thread-1--16 
Thread-1--17 Thread-1--18 Thread-1--19 Thread-1--20 Thread-1--21 
Thread-1--22 Thread-1--23 Thread-1--24 Thread-0--11 Thread-1--25 

 

明显不符合我们的程序初衷,中间的2无缘无故没了,这就是线程的安全问题了,所以要加入控制代码同步的锁,如下代码

package thread;

public class TestThread {
	private static int count;

	int line = 5;

	public static void main(String[] args) {
		TestThread tt = new TestThread();
		tt.startThread();
		tt.startThread();
	}

	class CountThread implements Runnable {
		public void run() {

			while (count < 25) {
				synchronized (TestThread.class) {
					if(count < 25){
						count++;
						System.out.print(Thread.currentThread().getName() + "--" + count + "\t");
						line--;
						if (line == 0) {
							System.out.println();
							line = 5;
						}
					}					
				}				
			}
		}
	}
	
	public void startThread() {
		new Thread(new CountThread()).start();
	}
}

 运行结果就为:

Thread-0--1 Thread-1--2 Thread-1--3 Thread-1--4 Thread-1--5 
Thread-1--6 Thread-0--7 Thread-0--8 Thread-0--9 Thread-0--10 
Thread-0--11 Thread-0--12 Thread-0--13 Thread-0--14 Thread-0--15 
Thread-0--16 Thread-0--17 Thread-0--18 Thread-0--19 Thread-0--20 
Thread-1--21 Thread-1--22 Thread-1--23 Thread-0--24 Thread-0--25 

这才是正常的,在程序代码中使用了两次判断count<25,这是因为这样可以让多个程序同时访问count,而不用等别的程序的while循环结束。

同步代码用的锁是一个对象,而且需要同步的代码所用的锁必须是一样的。

(转自CSDN) 

  • 同步代码块定义方法:
    • synchronized(对象)//这个对象可以是任意对象,例如Object,这样做是为了减小锁的粒度,建议使用更经济的空byte数组对象做锁。
      • //对象如同锁,持有锁的线程可以在同步中执行。没有锁的线程即使获取CPU的执行权,也进不去,因为没有获取锁。
    • {
      • 需要被同步的代码//这个代码不包括共享数据,只包括判断与结论等不能分割的数据。
    • }
  • 同步的前提:
    • 必须有两个或以上的线程。
    • 必须是多个线程使用同一个锁。必须保证同步中只能有一个线程在运行。
  • 同步的好处:
    • 解决了多线程的安全问题。
  • 同步的弊端:
    • 多个线程需要判断锁,较为消耗资源。
  • 哪些时候使用同步?
    • 1.明确哪些代码是多线程运行代码。
    • 2.明确共享数据。
    • 3.明确多线程运行代码中哪些语句是操作共享数据的。

(转自CSDN) 

另外,在函数的返回值类型前加上 synchronized声明,则成为同步函数,和同步代码块一个效果

 

上面的例子只是做到了同步,但是当多个线程对同一资源进行不同操作是,单是同步并不够,因为每个线程的运行条件不一样,比方说对一个仓库的操作,一个往里边加东西的线程需要判断里边有没有装满,一个从里边拿东西的线程则需要判断里边有没有东西,这两个判断都是基于仓库中的资源,所以需要同步,但是如果仓库满的话,那放东西的线程就必须休息一下,即是wait,那它什么时候醒呢?当然是有人叫醒它了,叫醒它的人就是和它有同样同步锁的拿东西的那个线程了,这就是线程的通信基本原理

  通信的时候需要注意的问题:

  1. 有三个以上的线程的时候,判断是否休息的语句用while,因为用if可能会让所有线程等待,if只判断一次。
  2. 有三个以上的线程的时候,叫醒用notifyAll,这样会避免叫醒的线程正好是和要去睡觉的线程是同一类,然后大家都睡觉了。

这里边的关系用一幅图来表示吧



 

当然这是最背的情况,实际情况更复杂,需要用配合代码来说明的。

 

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

详细请查看:http://edu.csdn.net

  • 大小: 29.5 KB
  • 大小: 3.2 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics