synchronized 关键字最佳实践

来源:互联网 发布:淘宝500的充气娃娃图片 编辑:程序博客网 时间:2024/05/18 01:06

Synchronization is the tool using which we can achieve thread safety, JVM guarantees that synchronized code will be executed by only one thread at a time. java keyword synchronized is used to create synchronized code and internally it uses locks on Object or Class to make sure only one thread is executing the synchronized code.

  • Java synchronization works on locking and unlocking of resource, before any thread enters into synchronized code, it has to acquire lock on the Object and when code execution ends, it unlocks the resource that can be locked by other threads. In the mean time other threads are in wait state to lock the synchronized resource.
  • We can use synchronized keyword in two ways, one is to make a complete method synchronized and other way is to create synchronized block.
  • When a method is synchronized, it locks the Object, if method is static it locks the Class, so it’s always best practice to use synchronized block to lock the only sections of method that needs synchronization.
  • While creating synchronized block, we need to provide the resource on which lock will be acquired, it can be XYZ.class or any Object field of the class.
  • synchronized(this) will lock the Object before entering into the synchronized block.
  • You should use the lowest level of locking, for example if there are multiple synchronized block in a class and one of them is locking the Object, then other synchronized blocks will also be not available for execution by other threads. When we lock an Object, it acquires lock on all the fields of the Object.
  • Java Synchronization provides data integrity on the cost of performance, so it should be used only when it’s absolutely necessary.
  • Java Synchronization works only in the same JVM, so if you need to lock some resource in multiple JVM environment, it will not work and you might have to look after some global locking mechanism.
  • Java Synchronization could result in deadlocks, check this post about deadlock in java and how to avoid them.
  • Java synchronized keyword cannot be used for constructors and variables.
  • It is preferable to create a dummy private Object to use for synchronized block, so that it’s reference can’t be changed by any other code. For example if you have a setter method for Object on which you are synchronizing, it’s reference can be changed by some other code leads to parallel execution of the synchronized block.
  • We should not use any object that is maintained in a constant pool, for example String should not be used for synchronization because if any other code is also locking on same String, it will try to acquire lock on the same reference object from String pool and even though both the codes are unrelated, they will lock each other.


意译:
1.执行synchronized code 首先要获取对象的锁,执行完释放锁。执行期间其他线程等待该对象锁。
2.synchronized 有两种使用方式:a,synchronized 整个方法;b,synchronized 代码块。
3.synchronized 整个方法,会锁住整个对象,如果是static 方法,则会锁住整个类;最好使用synchronized 代码块,只synchronized 必要的代码块。保证锁的代码范围最小化。
4.要锁代码块,就要有一个充当锁的类或者对象大家都来竞争这个锁。
5.synchronized(this)会锁整个this对象。慎用。
6.如果synchronized一个对象那么就会,那么就会synchronized 该对象的所有fields。若有一个代码块是要synchronized 该对象的某个field ,那么就要等待该对象被锁被释放。才能获得该对象该filed 的锁。故,要保持锁的级别最小。锁field够用就不要锁整个对象。
7.synchronized以性能为代价,保证数据完整性。非必要勿用。
8.synchronized仅适合单 jvm ,若多jvm 情况要用全局锁机制。
9.小心死锁哦,如何避免。
10.synchronized不能用了锁构造函数和变量。为什么呢?锁方法就要获得对象锁,亲在调用构造函数对象还没构造出来,上啥子锁。
11.最好有一个private Object 成员变量专门当用来上锁,而且不要有setter 方法。setter 方法可能改变该field 引用的对象,那上锁到不同对象,就起不到synchronized作用。
12.constant pool(常量池)里的对象不能用来上锁。两个没关系的代码块,都对同一个常量对象上锁,那么它们会产生竞争关系。


最佳实践的例子:
public class ThreadSafety {     public static void main(String[] args) throws InterruptedException {             ProcessingThread pt = new ProcessingThread();        Thread t1 = new Thread(pt, "t1");        t1.start();        Thread t2 = new Thread(pt, "t2");        t2.start();        //wait for threads to finish processing        t1.join();        t2.join();        System.out.println("Processing count="+pt.getCount());    } } class ProcessingThread implements Runnable{    private int count;    private Object lock = new Object();        @Override    public void run() {        for(int i=1; i< 5; i++){            processSomething(i);            synchronized(lock){                          count++;              }              }    }     public int getCount() {        return this.count;    }     private void processSomething(int i) {        // processing some job        try {            Thread.sleep(i*1000);        } catch (InterruptedException e) {            e.printStackTrace();        }    }     }





0 0
原创粉丝点击