关于线程同步:

假设有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());

    }
}

 

posted on 2022-05-18 09:11  OYYC  阅读(59)  评论(0编辑  收藏  举报