`
hongliangpan
  • 浏览: 319627 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

EffectiveJava2第67条:避免过多同步

 
阅读更多

第67条:避免过多同步

66条说了不同步的危险,本条讲的是过度同步的问题。过度同步,可能性能降低、死锁、或不确定的行为。

并发程序第一步要保证正确,第二步才是性能。

不能在同步区域内调用外部方法,缩小同步的代码范围。 

反面教材

集合Iterator时不能 remove元素否则会产生并发修改异常

  ConcurrentModificationException

// More complex test of ObservableSet - Page 267

import java.util.*;

public class Test2 {
    public static void main(String[] args) {
        ObservableSet<Integer> set =
            new ObservableSet<Integer>(new HashSet<Integer>());

        set.addObserver(new SetObserver<Integer>() {
            public void added(ObservableSet<Integer> s, Integer e) {
                System.out.println(e);
                if (e == 23) s.removeObserver(this);
            }
        });

        for (int i = 0; i < 100; i++)
            set.add(i);
    }
}

死锁例子

// Perverse test of ObservableSet - bottom of Page 267

import java.util.*;
import java.util.concurrent.*;

public class Test3 {
    public static void main(String[] args) {
        ObservableSet<Integer> set =
            new ObservableSet<Integer>(new HashSet<Integer>());

        // Observer that uses a background thread needlessly
        set.addObserver(new SetObserver<Integer>() {
            public void added(final ObservableSet<Integer> s, Integer e) {
                System.out.println(e);
                if (e == 23) {
                    ExecutorService executor =
                        Executors.newSingleThreadExecutor();
                    final SetObserver<Integer> observer = this;
                    try {
                        executor.submit(new Runnable() {
                            public void run() {
                                s.removeObserver(observer);
                            }
                        }).get();
                    } catch (ExecutionException ex) {
                        throw new AssertionError(ex.getCause());
                    } catch (InterruptedException ex) {
                        throw new AssertionError(ex.getCause());
                    } finally {
                        executor.shutdown();
                    }
                }
            }
        });

        for (int i = 0; i < 100; i++)
            set.add(i);
    }
}
// Broken - invokes alien method from synchronized block! - Page 265

import java.util.*;
import java.util.concurrent.*;

public class ObservableSet<E> extends ForwardingSet<E> {
    public ObservableSet(Set<E> set) { super(set); }

    private final List<SetObserver<E>> observers =
        new ArrayList<SetObserver<E>>();

    public void addObserver(SetObserver<E> observer) {
        synchronized(observers) {
            observers.add(observer);
        }
    }

    public boolean removeObserver(SetObserver<E> observer) {
        synchronized(observers) {
            return observers.remove(observer);
        }
    }

    // This method is the culprit
    private void notifyElementAdded(E element) {
        synchronized(observers) {
            for (SetObserver<E> observer : observers)
                observer.added(this, element);
        }
    }

    // Alien method moved outside of synchronized block - open calls - Page 268
//  private void notifyElementAdded(E element) {
//      List<SetObserver<E>> snapshot = null;
//      synchronized(observers) {
//          snapshot = new ArrayList<SetObserver<E>>(observers);
//      }
//      for (SetObserver<E> observer : snapshot)
//          observer.added(this, element);
//  }


    //  Thread-safe observable set with CopyOnWriteArrayList - Page 269
//
//  private final List<SetObserver<E>> observers =
//      new CopyOnWriteArrayList<SetObserver<E>>();
//
//  public void addObserver(SetObserver<E> observer) {
//      observers.add(observer);
//  }
//  public boolean removeObserver(SetObserver<E> observer) {
//      return observers.remove(observer);
//  }
//  private void notifyElementAdded(E element) {
//      for (SetObserver<E> observer : observers)
//          observer.added(this, element);
//  }

    @Override public boolean add(E element) {
        boolean added = super.add(element);
        if (added)
            notifyElementAdded(element);
        return added;
    }

    @Override public boolean addAll(Collection<? extends E> c) {
        boolean result = false;
        for (E element : c)
            result |= add(element);  // calls notifyElementAdded
        return result;
    }
}

集合添加对象 是同步方法,添加时又做其他删除的同步操作产生死锁。

删除对象的线程,想要获得对象锁,但是此对象已经被主线程锁了,所以产生死锁。

死锁最简单的例子

//代码一
class Deadlocker {
 int field_1;
 private Object lock_1 = new int[1];
 int field_2;
 private Object lock_2 = new int[1];

 public void method1(int value) {
  “synchronized” (lock_1) {
   “synchronized” (lock_2) {
    field_1 = 0; field_2 = 0;
   }
  }
 }

 public void method2(int value) {
  “synchronized” (lock_2) {
   “synchronized” (lock_1) {
    field_1 = 0; field_2 = 0;
   }
  }
 }
}



  参考代码一,考虑下面的过程:

  ◆ 一个线程(ThreadA)调用method1()。

  ◆ ThreadA在lock_1上同步,但允许被抢先执行。

  ◆ 另一个线程(ThreadB)开始执行。

  ◆ ThreadB调用method2()。

  ◆ ThreadB获得lock_2,继续执行,企图获得lock_1。但ThreadB不能获得lock_1,因为ThreadA占有lock_1。

  ◆ 现在,ThreadB阻塞,因为它在等待ThreadA释放lock_1。

  ◆ 现在轮到ThreadA继续执行。ThreadA试图获得lock_2,但不能成功,因为lock_2已经被ThreadB占有了。

  ◆ ThreadA和ThreadB都被阻塞,程序死锁。

分享到:
评论

相关推荐

    XYXDBP-WGP#Effective-Java#第67条:谨慎地进行优化 1cdaf9d873e44a30a04503f8b

    第67条:谨慎地进行优化有三条优化有关的格言是每个人都应该知道的:很多计算上的过失都被归咎于效率(没有达到必要的效率),而不是任何其他的原因 ,甚至包括盲目的做

    Effective Java第三版1

    《Effective Java》是Java编程领域的一本经典著作,由Joshua Bloch撰写,该书的第三版继续提供了关于如何编写高效、优雅、可维护的Java代码的指导。以下是基于给出的目录和部分内容提取的一些关键知识点: ### 第一...

    Effective Java读书笔记.pdf

    * 跨平台性:Java语言可以在多种平台上运行,包括Windows、Linux、Mac OS等。 * 安全性:Java语言具有内置的安全机制,保护用户免受恶意代码的攻击。 * 可靠性:Java语言具有强大的错误处理机制,能够快速恢复程序...

    effective-java.pdf

    标题“effective-java.pdf”与描述“effective-java.pdf”表明本文档是关于Java编程实践的指南,且内容可能来自于一本名为《Effective Java》的书籍,该书是由Joshua Bloch编写,被广泛认为是Java编程的权威指南。...

    effectiveJava课件分享

    在编程领域,特别是Java开发中,"Effective Java"是一本非常经典的书籍,由Joshua Bloch撰写,书中提出了一系列最佳实践和设计原则,以帮助开发者编写出更高效、更安全的代码。根据提供的标题和描述,我们将探讨三个...

    effective java 读书笔记

    - Item2:Builder模式适用于有大量构建参数的情况,它可以避免构造器的链式调用变得复杂且易出错。 - Item3:单例模式应使用私有构造子和静态工厂方法实现,确保只有一个实例存在。若需要线程安全,推荐使用枚举...

    Effective Java.zip

    - 接口的默认方法:Java 8引入的新特性,允许在接口中添加非抽象方法的实现,增强了接口的功能。 - 实现类的继承策略:建议尽量避免多层次的继承,提倡使用组合和接口来代替。 - 避免使用 finalize() 方法:由于...

    Effective java 3 学习记录.docx

    Effective Java 3 学习记录 本学习记录主要介绍了 Effective Java 3 中的静态工厂方法和 Builder 模式两部分内容。 一、静态工厂方法 静态工厂方法是指返回类实例的命名规则,例如:from、of、valueOf、instance ...

    《Effective Java》读书分享.pptx

    "Effective Java 读书分享" 《Effective Java》读书分享.pptx 是一本 Java 编程语言指南,旨在帮助开发者编写高质量、可维护的 Java 代码。该书包含 90 个条目,每个条目讨论一条规则,涵盖了 Java 编程语言的...

    effective-java 配套代码

    《Effective Java》是Java开发领域的一本经典著作,由Joshua Bloch撰写,书中提出了一系列编程最佳实践和设计模式,帮助开发者写出更高效、更可靠、更易于维护的Java代码。配套代码`effective-java-examples-master`...

    读书笔记:Effective Java中文版 第2版.zip

    读书笔记:Effective Java中文版 第2版

    Effective Java 3rd edition(Effective Java第三版英文原版)附第二版

    Item 2: Consider a builder when faced with many constructor parameters Item 3: Enforce the singleton property with a private constructor or an enum type Item 4: Enforce noninstantiability with a ...

    Effective.Enterprise.Java.中文版 高清pdf 下载

    《Effective Enterprise Java》也不例外,它旨在帮助开发者避免常见的陷阱,提升代码质量,并提高开发效率。书中的每个条目都是一个独立的建议,旨在解决实际开发中遇到的问题,这些条目通常以简洁明了的方式呈现,...

    Effective-Java:Effective Java中文版第二版示例代码

    《Effective Java》是Java开发领域的经典著作,由Joshua Bloch撰写,中文版第二版更是深受广大Java开发者喜爱。这本书提供了许多实用的编程实践和经验教训,帮助开发者编写出更高效、可维护的Java代码。这里我们将...

    effectiveJava的笔记

    《Effective Java》是Java开发领域的经典著作,由Joshua Bloch编写,旨在提供一系列实用的编程准则和最佳实践。这本书的第三版包含了大量更新,涵盖了Java语言和平台的新发展,如Java 8和Java 9的新特性。以下是对...

Global site tag (gtag.js) - Google Analytics