synchronized

本文探讨了如何使用Java中的synchronized关键字来解决线程安全问题,通过实例分析了修饰方法和同步代码块的不同效果。首先展示了synchronized修饰方法可能导致的性能下降和资源消耗,然后提出将synchronized应用于特定代码块以提高效率,最后强调了同步对象必须为对象引用而非基本类型。这些优化策略有助于在保证线程安全的同时提升程序性能。
摘要由CSDN通过智能技术生成

synchronized修饰方法

在前面的博客中我向大家展示了线程不安全的案例以及可能造成的危害,今天给大家讲解防止危险的方法。
我们可以使用synchronized关键字来修饰变量或方法
修饰方法之后,方法体中的this指针所指对象会被标记为同步对象。此时其他对象访问该对象会进入阻塞状态,只有对象被访问结束才会释放资源。
显而易见的是这种行为无疑会消耗更多的资源并降低程序的执行效率

package com.UnSafeDemo;

public class sellTickets extends Thread{

    @Override
    public synchronized void run() {
        sell();
    }

    private int tickets = 3;
    public static void main(String[] args) {
        sellTickets machine = new sellTickets();
        new Thread(machine,"张三").start();
        new Thread(machine,"李四").start();
        new Thread(machine,"黄牛党").start();
    }
    void sell()
    {

        while (this.tickets>0)
        {
            System.out.println(Thread.currentThread().getName()+"买走了第"+tickets+"张票");
            tickets--;
        }
    }
}


以上便是改良过的售票案例。
在这里插入图片描述
观察结果我们发现,确实解决掉了同一张票被多个人买到的问题。但是由于synchronized用来修饰run方法。导致张三在买票的时候全部买完,其他人才可以买,这种霸道的做法显然是我们不想看到的。

package com.UnSafeDemo;

public class sellTickets extends Thread {
    boolean flag = true;

    @Override
    public void run() {
        while (flag) {
            sell();
        }

    }

    private int tickets = 100000;

    public static void main(String[] args) {
        sellTickets machine = new sellTickets();
        new Thread(machine, "李四").start();

        new Thread(machine, "张三").start();
        new Thread(machine, "黄牛党").start();
    }

    synchronized void sell() {

        if (tickets <= 0) {
            flag = false;
            return;
        } else {
            System.out.println(Thread.currentThread().getName() + "买走了第" + tickets + "张票");
            tickets--;
        }


    }
}


这次我们把synchronized用来修饰sell方法,并把循环写到run方法之中。
这样程序无需等待每一张票全部卖完再释放锁,从而解决掉上述问题。

synchronized(obj){}同步代码块

这里的obj即为我们需要上锁的变化的且多个线程共享的变量,而{}中的代码为操作obj的代码段。
注意理论上来讲我们可以将一切资源及代码块上锁。但这样会大大降低性能。保证安全性的同时提高性能便是我们该做的事。

package com.UnSafeDemo;

public class sellTickets extends Thread {
    boolean flag = true;

    @Override
    public void run() {
        synchronized (tickets)
        {
            while (flag) {
                sell();
            }
        }
    }

    private Integer tickets = 10;

    public static void main(String[] args) {
        sellTickets machine = new sellTickets();
        new Thread(machine, "李四").start();

        new Thread(machine, "张三").start();
        new Thread(machine, "黄牛党").start();
    }

     void sell() {

            if (tickets <= 0) {
                flag = false;
                return;
            } else {
                System.out.println(Thread.currentThread().getName() + "买走了第" + tickets + "张票");
                tickets--;
            }




    }
}


这里一定要注意!被synchronized中的被上锁的变量一定是object类型或者其子类,如果使用基础数据类型如int float 会报错,应使用其相应的包装类如Interger
由于在run方法中的sell方法多个线程均可访问到变量tickets ,我们只需要
synchronized(tickets){sell()}即可实现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值