java 线程安全,一个函数前用 sychronized 修饰后,这个函数就能做到线程安全么,具体是达到什么程度的线程安全呢?

一个函数前用 sychronized 修饰后,这个函数就能做到线程安全么,具体是达到什么程度的线程安全呢?

把一个类的所有成员函数都加上 sychronized,有什么好处和弊端呢?

阅读 3.5k
3 个回答

多线程的安全是不是线程本身安全,而是指的是多线程场景下安全的操作共享资源。这里的共享资源可能是一个变量,也可能是一个业务状态,而这个状态由多个变量维护。在默认不加限制的情况下,多个线程读写共享资源,会遇到原子性和一致性的问题。要解决这些问题就要用多线程工具来控制对共享资源的访问,比如synchronized就是一种方式,对所有共享资源的读写操作都使用synchronized来保护,就可以实现对这个共享状态的串行读写,并且可见性也得到了JMM的保证。

把一个类的所有成员函数都加上sychronized,单纯这么做是没有意义的,要思考的是如何处理共享资源并发操作的问题。

加上sychronized的代码,会保证,无论什么时候,只能有1个线程执行里面的内容

官方解释在这里。

8.4.3.6. synchronizedMethods

需要理解monitor和thread的关系,这个问题你就明白了

Java 中的所有对象都可以扮演锁的角色,synchronized 可以用在三个地方,用在不同地方的锁对象也不同。
1.用在普通方法,锁是当前实例对象。在这个例子中就是 Test 类的实例对象。

class Test {
    public static synchronized void test() {
       ...
    }
}

2.用在静态方法,锁是当前类的 Class 对象,也就是类加载时创建的 Class 对象,不知道你是否了解类加载机制。

class Test {
    public static synchronized void test() {
           ...
    }
}

3.用在方法块,锁是 synchonized 括号里配置的对象。

class Test {

    Object object = new Object();

     public void test() {
         synchronized(object){
           ...
         }
     }
}

对于你的问题,在普通方法上使用 synchonized 时,锁就是当前的实例对象,在多线程环境中,线程会竞争获取这把锁,只有拿到锁的情况下才可执行该方法,这样就确保了同一时间只能有一个线程执行这个同步方法。

至于把一个类的所有方法都加上 sychronized 的好处与弊端:

JDK 中的 Hashtable 就是这么做的,在所有主要方法都使用了 synchronized 关键字,好处是保证了线程安全,弊端就是效率太低,现在已不推荐使用。可以看下这篇文章Hashtable,SynchronizedMap和ConcurrentHashMap线程安全实现的区别以及性能测试

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题