Synchronized使用

Synchronized是线程同步关键字

第一种:
属于锁当前对象,方法锁和synchronized (this)属于一个锁

public class ReentrantThread {
    public static void main(String[] args) throws InterruptedException {
        ReentrantObject reentrantObject=new ReentrantObject();
       Thread t1=new MyThread(reentrantObject);
       t1.start();
       Thread t2=new HisThread(reentrantObject);
       t2.start();
    }
}
class MyThread extends Thread{
    private ReentrantObject reentrantObject;
    public MyThread(ReentrantObject reentrantObject){
        this.reentrantObject=reentrantObject;
    }

    @Override
    public void run() {
        try {
            reentrantObject.say1();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
class HisThread extends Thread{
    private ReentrantObject reentrantObject;
    public HisThread(ReentrantObject reentrantObject){
        this.reentrantObject=reentrantObject;
    }

    @Override
    public void run() {
        try {
            reentrantObject.say2();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
class ReentrantObject{
    public synchronized   void say1() throws InterruptedException {
        System.out.println("say1");
        Thread.sleep(5000);
    }

    public  void say2() throws InterruptedException {
        synchronized (this){
            System.out.println("say2");
            Thread.sleep(2000);
        }
    }
}

第二种:
静态方法锁和synchronized(ReentrantObject.class)是一个锁

public class ReentrantThread {
    public static void main(String[] args) throws InterruptedException {
        ReentrantObject reentrantObject=new ReentrantObject();
       Thread t1=new MyThread(reentrantObject);
       t1.start();
       Thread t2=new HisThread(reentrantObject);
       t2.start();
    }
}
class MyThread extends Thread{
    private ReentrantObject reentrantObject;
    public MyThread(ReentrantObject reentrantObject){
        this.reentrantObject=reentrantObject;
    }

    @Override
    public void run() {
        try {
            reentrantObject.say1();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
class HisThread extends Thread{
    private ReentrantObject reentrantObject;
    public HisThread(ReentrantObject reentrantObject){
        this.reentrantObject=reentrantObject;
    }

    @Override
    public void run() {
        try {
            reentrantObject.say2();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
class ReentrantObject{
    public synchronized static  void say1() throws InterruptedException {
        System.out.println("say1");
        Thread.sleep(5000);
    }

    public static void say2() throws InterruptedException {
        synchronized (ReentrantObject.class){
            System.out.println("say2");
            Thread.sleep(2000);
        }
    }
}

一般不使用常量字符串作为锁对象。

对象同步锁,锁的是当前变量指向的对象。对象的属性发生变化时,不会影响结果。

public class SynchronizedSketch {
    public static void main(String[] args) throws InterruptedException {
        LockObject lockObject=new LockObject();
        LockThread lockThread=new LockThread(lockObject);
        lockThread.setName("1");
        lockThread.start();

        Thread.sleep(1000);

        LockThread lt=new LockThread(lockObject);
        lt.setName("2");
        lt.start();
    }
    static class LockObject{
        String name;
    }
    static class LockThread extends Thread{
        LockObject lockObject;
        public LockThread(LockObject lockObject){
            this.lockObject=lockObject;
        }

        @Override
        public void run() {
            synchronized (lockObject){
                System.out.println(this.getName()+"线程执行了");
                lockObject.name="4";
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(this.getName()+"线程执行完了");
            }
        }
    }
}

执行结果:

1线程执行了
1线程执行完了
2线程执行了
2线程执行完了

上面的执行是同步的。

下面测试同步变量 的指向 发生变化时,是否会导致同步变化

public class SynchronizedSketch {
    public static void main(String[] args) throws InterruptedException {
        LockObject lockObject=new LockObject();
        LockThread lockThread=new LockThread(lockObject);
        lockThread.setName("1");
        lockThread.start();
        LockThread lt=new LockThread(lockObject);
        lt.setName("2");
        Thread.sleep(1000);


        lt.start();
    }
    static class LockObject{
        String name;
    }
    static class LockThread extends Thread{
        LockObject lockObject;
        public LockThread(LockObject lockObject){
            this.lockObject=lockObject;
        }

        @Override
        public void run() {
            System.out.println("run方法执行"+this.getName());
            synchronized (lockObject){
                System.out.println(this.getName()+"进入线程同步块");
                System.out.println(lockObject);
                lockObject=new LockObject();
                System.out.println(lockObject);
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(this.getName()+"线程离开同步块");
            }
        }
    }
}

执行结果:

run方法执行1
1进入线程同步块
com.liu.thread.SynchronizedSketch$LockObject@77355386
com.liu.thread.SynchronizedSketch$LockObject@79f2b310
run方法执行2
1线程离开同步块
2进入线程同步块
com.liu.thread.SynchronizedSketch$LockObject@77355386
com.liu.thread.SynchronizedSketch$LockObject@503c95b4
2线程离开同步块

可以看出,线程是同步的,因为2个线程锁的都是 同一个对象, 地址为386结尾。

而给lockObject加上static修饰符,则结果就不一样了
static class LockThread extends Thread{
static LockObject lockObject;
public LockThread(LockObject lockObject){
this.lockObject=lockObject;
}
运行结果:

run方法执行1
1进入线程同步块
com.liu.thread.SynchronizedSketch$LockObject@3b637176
com.liu.thread.SynchronizedSketch$LockObject@35a4886a
run方法执行2
2进入线程同步块
com.liu.thread.SynchronizedSketch$LockObject@35a4886a
com.liu.thread.SynchronizedSketch$LockObject@503c95b4
1线程离开同步块
2线程离开同步块

可以看出2个线程并不同步。因为他们访问的不是同一个对象锁。

再来一个例子:

public class SynchronizedSketch2 {
    public static void main(String[] args) throws InterruptedException {
        Person lockObject=new Person();
        lockObject.setName("wang");
        MyThread lockThread=new MyThread(lockObject);
        lockThread.setName("1");
        lockThread.start();
        MyThread lt=new MyThread(lockObject);
        lt.setName("2");
        Thread.sleep(1000);
        lt.start();
    }
    static class MyThread extends Thread{
        Person person ;
        public MyThread(Person person){
            this.person=person;
        }

        @Override
        public void run() {
            System.out.println("run方法执行"+this.getName());
            person.tellYouIamWho();

        }
    }
}
class Person{
    private String Name;

    public String getName() {
        return Name;
    }

    public void setName(String name) {
        Name = name;
    }

    public void tellYouIamWho(){
        synchronized (Name){
            System.out.println(this.getName()+"进入线程同步块");
            System.out.println(Name);
            Name="li";
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程离开同步块");
        }
    }
}

运行结果:

run方法执行1
wang进入线程同步块
wang
run方法执行2
改了进入线程同步块
改了
线程离开同步块
线程离开同步块

可以看出,并不是同步的。因为用的不是同一个对象的锁。

在Java中,synchronized关键字用于实现线程之间的同步。它可以应用于方法或代码块上。在方法上使用synchronized关键字,可以确保同一时间只有一个线程可以访问该方法。而在代码块上使用synchronized关键字,可以确保同一时间只有一个线程可以访问被同步的代码块。 在引用中,演示了在同步代码块中使用synchronized关键字的情况。在SynchronizedDemo类的method方法中,使用synchronized关键字来同步代码块,以保证线程安全。 引用展示了子类继承父类,并重写了同步方法的情况。在SynchronizedUsageChild类的synchronizedMethod1方法中,通过使用synchronized关键字来同步方法,确保在多线程环境下,同一时间只有一个线程可以访问该方法。在该方法中,还演示了可重入锁的概念,即子类在同步方法中调用父类的同步方法。 总结来说,synchronized关键字用于实现线程之间的同步,可以应用于方法或代码块上,以确保多线程环境下的线程安全性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Synchronized 详解](https://blog.csdn.net/qq_43322057/article/details/104258758)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Java synchronized使用案例](https://download.csdn.net/download/visionliao/8368107)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [synchronized用法详解](https://blog.csdn.net/ganmaotong/article/details/124501478)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值