关于线程同步:
假设有1个英雄攻击盖伦且每次hp-1,可是盖伦自身也在每秒回1hp,攻击和回血两个线程同时执行,线程结束后盖伦的血量因还是10000,但是
分析原因:
但加血线程还未执行完时,减血线程又开始执行了,所以当线程执行完时hp=10000才对,可因为减血线程的加入导致hp=9999,此问题在业务上叫做脏数据。
解决方法:
在加血线程执行期间,减血线程对hp的值的访问不被允许
在加血线程执行完成之后,才可被访问;
synchronized对象又叫做同步对象
synchronized表示当前线程占用着someobject
在占用期间其他线程不可占用someobject,直到线程
执行完毕并被释放。
结束方式:代码块自然结束或者有异常抛出。
2、同步对象也可以换成其他对象
this表示当前同步的对象,也就是gailun
3、直接在方法前加上修饰符
这与2达成的效果一样
如果一个类的方法中有用synchronized修饰的话,那么此类
叫做线程安全的类。
案例:
public class Thread_Synchronization { public static void main(String arg[]){ final Object someobject =new Object(); KillThread gailun =new KillThread(10000,10,"盖伦"); final int n = 1000; Thread[] T1 =new Thread[ n ]; Thread[] T2 =new Thread[ n ]; for(int i =0;i<n;i++){ Thread t1 = new Thread(){ public void run(){ //任何线程需要修改hp的值都需要先占有someobject synchronized ( someobject ) { gailun.hurt(); } try { sleep(1000); }catch (InterruptedException e){ e.printStackTrace(); } } }; t1.start(); T1[i] = t1; } for(int a =0;a<n;a++){ Thread t2 = new Thread(){ public void run(){ //任何线程需要修改hp的值都需要先占有someobject synchronized ( someobject ) { gailun.urt(); } try { sleep(1000); }catch (InterruptedException e){ e.printStackTrace(); } } }; t2.start(); T2[a] = t2; } for(Thread Tone:T1){ try{ Tone.join(); }catch (InterruptedException e){ e.printStackTrace(); } } for(Thread Ttwo:T2){ try{ Ttwo.join(); }catch (InterruptedException e){ e.printStackTrace(); } } System.out.printf("%d个增加线程和%d个减血线程后%n盖伦的血量是%d",n,n,gailun.getHp()); } }