synchronized同步静态方法是的使用注意实现

先明确几点:

1、所有synchronized修饰的非静态方法用的都是同一把锁:实例对象本身

2、所有synchronized修饰的静态方法用的都是同一把锁:类对象本身

3、而对于同步块,由于其锁是可以选择的,所以只有使用同一把锁的同步块之间才有着竞态条件

好了,请看如下代码

class CsdnMain{
    public static void main(String[] args){
        List<Ipbean> ipbeanList=new ArrayList<>();//假设里面已经有100个数据了
        for (int i=0;i<3;i++){
            Thread thread=new Thread(new Runnable(){
                @Override
                public void run() {
                    Csdn.filter(ipbeanList);
                }
            });
            thread.start();
        }
    }
}

class Csdn{
    public static List<Ipbean> tenders=new ArrayList<>();
    public static synchronized void add(Ipbean ipbean){
        tenders.add(ipbean);
    }

    public static synchronized void filter(List<Ipbean> ipbeanList) throws InterruptedException {
        if (ipbeanList==null)return;
        for (Ipbean ipbean:ipbeanList){
            if ("http".equals(ipbean.getType().toLowerCase())){
                Thread thread=new Thread(new Runnable(){
                    @Override
                    public void run() {
                        add(ipbean);
                    }
                });
                thread.start();
                thread.join();
            }

        }
    }
}

你觉得这个代码能够正常执行完毕吗?

答案是:不一定

如果列表中的IP都不是走http协议的 那么这个程序确实会正确执行完毕,但是如果有一个走http协议的 那就会出现死锁

原因如下:

       当某一个线程在执行filter时,如果满足执行add的条件,那么该线程会新建另外一个线程去执行add方法,那么就出问题了,Csdn这个类对象锁此时挂在"该线程"上,没有被释放,而在其内部创建去执行add方法的线程也需要Csdn这个类对象锁,一个需要锁,一个不放锁,并且不放锁的又需要要锁的线程执行完毕才能继续执行,死锁就出现了。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值