synchronized方法的安全问题

1      常见问题

synchronized方法是一种常用的线程同步方法,在我们代码中多处使用。但是使用不当的情况下容易引入安全问题,因此《Java编码安全Checklist_V2.0》中专门设置了一个检查项:

与非信任代码交互的类的同步操作要使用私有的、无法被非信任代码访问与修改的锁

举例如下:

1)SomeObject类中定义了一个同步方法changeValue()。

public class SomeObject

{

    // Locks on the object's monitor

    public synchronized void changeValue()

    {

        // . . .

    }

}

 

2)非信任代码通过某种方法获取到了一个SomeObject对象,对其加锁,并且长期持有该锁。

// Untrusted code

SomeObject theObject = getTheObject();

synchronized (someObject)

{

    while (true)

    {

        // Indefinitely delay someObject

        Thread.sleep(Integer.MAX_VALUE);

    }

}

 

3)其他代码在调用该对象的changeValue方法时无法获取锁,将长期被阻塞。

// Trusted code

SomeObject theObject = getTheObject();

theObject.changeValue();  //调用对象的同步方法时,需要先获取对象锁。

2     修改方法

2.1     最小化暴露

一般来说,同一个package中的代码可以认为是可信任的。

如果一个类只是供同一个package中的代码访问,那么该类声明为default就够了(即不加任何访问控制符),不需要声明为public,这样就天然解决了这个问题。

说句题外话,我们在编码时经常习惯性的把所有的类都声明为public,实际上大多数类都不需要这么大的访问权限,我们应该根据实际情况来选择合适的访问控制符,做到最小化暴露。

附:访问控制级别表:

 

private

default

protected

public

同一个类中

Yes

Yes

Yes

Yes

同一个包中

 

Yes

Yes

Yes

子类中

 

 

Yes

Yes

全局范围内

 

 

 

Yes

2.2     使用私有锁对象

如果使用同步方法的类确实需要声明为public,可以使用私有锁对象习语(private lock object idiom)来进行同步。该习语使用类中声明的私有不变(private final)java.lang.Object实例所关联的隐式锁来代替类对象本身的隐式锁。这个习语要求在类方法中使用同步块而不是使用同步方法。因为敌对类不能访问这个私有不变锁对象,因此它没法与该类中的方法进行锁竞争。当一个类可能与非信任代码交互时,使用私有不变锁对象对这个类中的代码做同步。

public class SomeObject

{

    private final Object lock = new Object(); // private final lock object

   

    public void changeValue()

    {

        synchronized (lock)

        {

            // Locks on the private Object

            // ...

        }

    }

}

转载于:https://my.oschina.net/u/1413984/blog/809486

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值