线程的同步-同步块

线程的同步,除了同步方法外,我们还可以使用代码块,使用代码块比同步方法有更好的效果。。
追其同步的根本目的,是控制竞争资源的正确访问,因此只要在访问竞争资源的时候,只要保证同一时刻只能有一个线程访问即可,因此Java引入了同步代码块的策略,以提高其性能。我们对上一篇文章进行改进:
User类:

package thread_synchronization;

public class User {

    private String code;//账号
    private int cash;//金额

    public User(String code,int cash){
        this.code=code;
        this.cash=cash;
    }
    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public int getCash() {
        return cash;
    }

    public void setCash(int cash) {
        this.cash = cash;
    }

    /**
     * (1)、使用synchronized代码块
     * (2)、计算剩余额度
     * (3)、使用synchronized锁定线程对象,实现线程同步,从而保证计算结果的正确性,如果去掉synchronized,数据会发生错误,是错误的
     * @param x
     */
    public void oper(int x){
        try {
            Thread.sleep(10L);
            synchronized (this){
                this.cash+=x;
                System.out.println(Thread.currentThread().getName()+"运行结束,增加"+x+","+"当前余额剩余为:"+cash);
            }
            Thread.sleep(10L);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public String toString() {
        return "User{" + "code='" + code + '\'' + ",cash=" + cash + '}';
    }
}

ThreadExtend_Synchronization类

public class ThreadExtend_Synchronization extends Thread{

    private User user;
    private int y;

    ThreadExtend_Synchronization(String name, User user, int y){
        super(name);
        this.user=user;
        this.y=y;
    }
    @Override
    public void run() {
        user.oper(y);
    }

    public static void main(String args[]){
        User user=new User("张三",100);
        Thread thread1=new ThreadExtend_Synchronization("线程A",user,1);
        Thread thread2=new ThreadExtend_Synchronization("线程B",user,2);
        Thread thread3=new ThreadExtend_Synchronization("线程C",user,3);
        Thread thread4=new ThreadExtend_Synchronization("线程D",user,4);
        Thread thread5=new ThreadExtend_Synchronization("线程E",user,-10);
        Thread thread6=new ThreadExtend_Synchronization("线程F",user,-20);
        Thread thread7=new ThreadExtend_Synchronization("线程G",user,-30);
        Thread thread8=new ThreadExtend_Synchronization("线程H",user,-40);
        Thread thread9=new ThreadExtend_Synchronization("线程I",user,-50);
        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();
        thread5.start();
        thread6.start();
        thread7.start();
        thread8.start();
        thread9.start();
    }
}

运行结果如下:

线程C运行结束,增加3,当前余额剩余为:103
线程B运行结束,增加2,当前余额剩余为:105
线程A运行结束,增加1,当前余额剩余为:106
线程D运行结束,增加4,当前余额剩余为:110
线程E运行结束,增加-10,当前余额剩余为:100
线程H运行结束,增加-40,当前余额剩余为:60
线程F运行结束,增加-20,当前余额剩余为:40
线程G运行结束,增加-30,当前余额剩余为:10
线程I运行结束,增加-50,当前余额剩余为:-40

注意:使用synchronized关键字的时候,应该尽可能的避免在synchronized方法或者在synchronized块当中使用sleep或者yield方法,因为synchronized占用着对象锁,使用了sleep()方法以后,只能等待着它醒来以后,其它线程才能执行,这样的话严重影响了效率,也不符合逻辑。

线程同步小结:
1、线程同步的目的是多个线程访问一个资源造成对资源的破坏。
2、线程同步的方法是通过锁来实现,每个对象都有且仅有一个锁,线程一旦获得了对象锁,那么其访问该对象的线程就无法再访问该对象的其它线程。
3、对于静态同步方法,锁是针对这个类的,锁对象是该类的Class对象,静态和非静态方法的锁互不干预。
4、对于同步,要时刻清醒在哪个对象上进行同步,这是关键。
5、当多个线程等待一个对象锁的时候,没有获得锁的线程将发生阻塞。
6、死锁是线程间相互等待锁造成的,在实际应用当中发生的机率很小。

猜你喜欢

转载自blog.csdn.net/qq_24630433/article/details/88237948