多个线程同时修改统一数据造成错误的数据输出叫做多线程的同步问题
这是因为同时访问同一变量,当一个线程还未返回结果作为下一线程的参数时,下一线程已经开始,最后的结果也就是最后一个线程最后结束时变量最后改变的结果
synchronized表示当前线程,独占 对象 someObject
表示这个线程都占了此对象
其他线程要想进行就得等待此进程得结束也就是 synchronized 块自然结束
package multiplethread;
import java.awt.GradientPaint;
import charactor.Hero;
public class TestThread {
public static void main(String[] args) {
final Object someObject = new Object();
final Hero gareen = new Hero();
gareen.name = "盖伦";
gareen.hp = 10000;
int n = 10000;
Thread[] addThreads = new Thread[n];
Thread[] reduceThreads = new Thread[n];
for (int i = 0; i < n; i++) {
Thread t = new Thread(){
public void run(){
//任何线程要修改hp的值,必须先占用someObject
synchronized (someObject) {
gareen.recover();
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
t.start();
addThreads[i] = t;
}
for (int i = 0; i < n; i++) {
Thread t = new Thread(){
public void run(){
//任何线程要修改hp的值,必须先占用someObject
synchronized (someObject) {
gareen.hurt();
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
t.start();
reduceThreads[i] = t;
}
for (Thread t : addThreads) {
try {
t.join();//调用此线程,等待本线程执行结束,前面配合synchronized实例化数组时已经start单独占用cpu开始了,再sleep(),然后用join让他单独调用,即使在sleep()也要等待
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for (Thread t : reduceThreads) {
try {
t.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.printf("%d个增加线程和%d个减少线程结束后%n盖伦的血量是 %.0f%n", n,n,gareen.hp);
}
}
————————————————————————————————————————————————————————
for (int i = 0; i < n; i++) {
Thread t = new Thread(){
public void run(){
//使用gareen作为synchronized
synchronized (gareen) {
gareen.recover();
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
t.start();
addThreads[i] = t;
}
————————————————————————————————————————————————————————
还可以在方法前加入synchronized
public
synchronized
void
recover(){
hp=hp+
1
;
}
所对应的同步对象就是this档期那调用此方法的对象
————————————————————————————————————————————————————————
如果一个类,其方法都是有synchronized修饰的,那么该类就叫做线程安全的类
同一时间,只有一个线程能够进入 这种类的一个实例 的去修改数据,进而保证了这个实例中的数据的安全(不会同时被多线程修改而变成脏数据)
比如StringBuffer和StringBuilder的区别
StringBuffer的方法都是有synchronized修饰的,StringBuffer就叫做线程安全的类
而StringBuilder就不是线程安全的类