---------------------- 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的执行权,也进不去,因为没有获取锁。
- {
- 需要被同步的代码//这个代码不包括共享数据,只包括判断与结论等不能分割的数据。
- }
- synchronized(对象)//这个对象可以是任意对象,例如Object,这样做是为了减小锁的粒度,建议使用更经济的空byte数组对象做锁。
- 同步的前提:
- 必须有两个或以上的线程。
- 必须是多个线程使用同一个锁。必须保证同步中只能有一个线程在运行。
- 同步的好处:
- 解决了多线程的安全问题。
- 同步的弊端:
- 多个线程需要判断锁,较为消耗资源。
- 哪些时候使用同步?
- 1.明确哪些代码是多线程运行代码。
- 2.明确共享数据。
- 3.明确多线程运行代码中哪些语句是操作共享数据的。
(转自CSDN)
另外,在函数的返回值类型前加上 synchronized声明,则成为同步函数,和同步代码块一个效果
上面的例子只是做到了同步,但是当多个线程对同一资源进行不同操作是,单是同步并不够,因为每个线程的运行条件不一样,比方说对一个仓库的操作,一个往里边加东西的线程需要判断里边有没有装满,一个从里边拿东西的线程则需要判断里边有没有东西,这两个判断都是基于仓库中的资源,所以需要同步,但是如果仓库满的话,那放东西的线程就必须休息一下,即是wait,那它什么时候醒呢?当然是有人叫醒它了,叫醒它的人就是和它有同样同步锁的拿东西的那个线程了,这就是线程的通信基本原理
通信的时候需要注意的问题:
- 有三个以上的线程的时候,判断是否休息的语句用while,因为用if可能会让所有线程等待,if只判断一次。
- 有三个以上的线程的时候,叫醒用notifyAll,这样会避免叫醒的线程正好是和要去睡觉的线程是同一类,然后大家都睡觉了。
这里边的关系用一幅图来表示吧
当然这是最背的情况,实际情况更复杂,需要用配合代码来说明的。
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
详细请查看:http://edu.csdn.net