《JAVA并发编程实践》的原文摘录

  • 加锁机制既可以确保可见性又可以确保原子性,而 volatile 变量只能确保可见性。 当且仅当满足以下所有条件时,才应该使用 volatile 变量: - 对变量的写入操作不依赖变量的当前值,或者你能确保只有单个线程更新变量的值。 - 该变量不会与其它状态变量一起纳入到不变性条件中。 - 在访问变量时不需要加锁。 (查看原文)
    红色有角F叔 20回复 3赞 2014-05-07 09:42:03
    —— 引自章节:volatile 变量
  • 当满足以下条件时,对象才是不可变的: - 对象创建以后其状态就不可修改 - 对象的所有域都是 final 类型 - 对象时正确创建的(在对象的构造期间,this 引用没有逸出) 从技术上来看,不可变对象并不需要将其所有的域都声明为 final 类型,例如 String 就是这种情况,这就要对类的良性数据竞争情况做精确的分析,因此需要深入理解 Java 的内存模型。... 自己在编码时不要这么做。 (查看原文)
    红色有角F叔 1赞 2014-05-09 00:07:06
    —— 引自章节:不变性
  • 对于计算密集的任务,在拥有 N 个处理器的系统上,当线程池大小为 N+1 时,通常能实现最优的利用率。(即使当计算密集型的线程偶尔由于页缺失故障或者其它原因而暂停时,这个“额外”的线程也能确保 CPU 的时钟周期不会被浪费。)对于包含 I/O 操作或者其它阻塞操作的任务,由于线程并不会一直执行,因此线程池的规模应该更大。 计算每个任务对该资源的需求量,然后用该资源的可用总量除以每个任务的需求量,所得结果就是线程池大小的上限。 (查看原文)
    红色有角F叔 6回复 1赞 2014-05-31 12:32:42
    —— 引自章节:设置线程池的大小
  • 当任务需要某种通过资源池来管理的资源时,例如数据库连接,那么线程池和资源池的大小将会相互影响。如果每个任务都需要一个数据库连接,那么连接池的大小就限制了线程池的大小。同样,当线程池中的任务是数据库连接的唯一使用者时,那么线程池的大小又将限制连接池的大小。 (查看原文)
    红色有角F叔 6回复 1赞 2014-05-31 12:32:42
    —— 引自章节:设置线程池的大小
  • final域能确保初始化过程的安全性,从而可以不受限制的访问不可变对象,并在共享这些对象时无需同步。 (查看原文)
    peiyuc 1赞 2016-07-22 19:33:30
    —— 引自第39页
  • 只有当volatile变量能够简化实现和同步策略的验证时,才使用它们。当验证正确性必须推断可见性问题时,应该避免使用volatile变量。正确使用volatile变量的方式包括:用于确保它们所引用的对象的状态的可见性,或者用于标识重要的生命周期事件(比如初始化或关闭)的发生。 (查看原文)
    Heyton007 1赞 2017-06-24 09:12:06
    —— 引自第38页
  • To publish an object safely, both the reference to the object and the object's state must be made visible to other threads at the same time. A properly constructed object can be safely published by: Initializing an object reference from a static initializer; Storing a reference to it into a volatile field or AtomicReference; Storing a reference to it into a final field of a properly constructed object; or Storing a reference to it into a field that is properly guarded by a lock (查看原文)
    JackChu 2011-10-12 10:23:26
    —— 引自章节:第三章 共享对象
  • Our goal is to give readers a set of design rules and mental models that make it easier—and more fun—to build correct, performant concurrent classes and applications in Java. (查看原文)
    stephansun 2011-10-31 20:20:53
    —— 引自章节:序言
  • Threads are sometimes called lightweight processes, and most modern operating systems treat threads, not processes, as the basic units of scheduling. (查看原文)
    stephansun 2011-10-31 20:38:25
    —— 引自第2页
  • Using multiple threads can also help achieve better throughput on singleprocessor systems. If a program is single-threaded, the processor remains idle while it waits for a synchronous I/O operation to complete. In a multithreaded program, another thread can still run while the first thread is waiting for the I/O to complete, allowing the application to still make progress during the blocking I/O. (This is like reading the newspaper while waiting for the water to boil, rather than waiting for the water to boil before starting to read.) (查看原文)
    stephansun 2011-10-31 20:42:03
    —— 引自第3页
  • Historically, operating systems placed relatively low limits on the number of threads that a process could create, as few as several hundred (or even less). As a result, operating systems developed efficient facilities for multiplexed I/O, such as the Unix select and poll system calls, and to access these facilities, the Java class libraries acquired a set of packages (java.nio) for nonblocking I/O. However, operating system support for larger numbers of threads has improved significantly, making the thread-per-client model practical even for large numbers of clients on some platforms. (查看原文)
    stephansun 2011-10-31 20:46:44
    —— 引自第4页
  • Operating systems evolved to aloowed more than one programm to run at once, running individual programs in processes:isolated, independently executing programs to which the operationg system allocates resources such as memory,file handles, and security credentials. If they needed to,processes could communicate with one another through a variety of coarse-grained communicateion mechanisms:sockets,signal handlers,shared memory,semaphores, and files (查看原文)
    [已注销] 2011-12-21 10:48:04
    —— 引自第2页
  • The same concerns(resources utilization,fairness,and convenience) that motivated the development of progresses also motivated the development of threads. Threads allow multiple streams of program control flow to coexsit within a progress. They share process-wide resources such as memory and file handles, but each thread has its own program counter,stack, and local variables. Threads also provide a natural decomposition for exploiting hardware parallelism on multiprocessor systems; multiple threads within the same program can be scheduled simultaneously on multiple CPUs. (查看原文)
    [已注销] 2011-12-21 10:48:04
    —— 引自第2页
  • Informally, an object's state is its data, stored in state variables such as instance or static fields. An object's state may include fields from other, dependent objects; a HashMap's state is partially stored in the HashMap object itself, but also in many Map.Entry objects. An object's state encompasses any data that can affect its externally visible behavior. (查看原文)
    [已注销] 2011-12-22 13:47:48
    —— 引自第11页
  • 在一些大型程序中,要找出多个线程在哪些位置上将访问同一个变量是非常复杂的。幸运的是,面向对象这种技术不仅有助于编写出结构优雅、可维护性高的类,还有助于编写出线程安全的类。访问某个变量的代码越少,就越容易确保对变量的所有访问都实现正确的同步,同时也更容易找出变量再哪些条件下被访问。 程序的封装性越好,就越容易实现程序的县城安全性,并且代码的维护人员也越容易保持这种方式。 完全由线程安全类构成的程序不一定是线程安全的,而在线程安全类中也可以包含非线程安全的类。 正确性的含义是指,某个类的行为与其规范完全一致。在良好的规范中通常会定义各种不变性条件(Invariant)来约束对象的状态,以及定义各种后验条件(Postconditions)来描述对象操作的结果。 任何情况下,只有当类中仅包含自己的状态时,线程安全类才是有意义的。 通常,线程安全性的需求并非来源于对线程的直接使用,而是使用像 Serverlet 这样的框架。 最常见的竞态条件类型就是“先检查后执行”操作,即通过一个可能失败的观测结果来决定下一步的动作。 (查看原文)
    红色有角F叔 2014-05-02 21:59:27
    —— 引自章节:线程安全性
  • 当执行时间较长的计算或者可能无法快速完成的操作(例如网络IO或控制台IO)时,一定不要持有锁。 (查看原文)
    红色有角F叔 2014-05-03 09:33:19
    —— 引自章节:线程安全性
  • 无论其她的线程会对已发布的引用执行何种操作,其实都不重要,因为误用该引用的风险始终存在。 如果有人窃取了你的密码并发布到 alt.passwords 新闻组上,那么你的信息将 “逸出”:无论是否有人会恶意地使用这些个人信息,你的账户都已经不再安全了。发布一个引用同样会带来类似的风险。 (查看原文)
    红色有角F叔 2回复 2014-05-07 10:22:03
    —— 引自章节:发布与逸出
  • 一种避免使用同步的方式就是不共享数据。如果仅在单线程内访问数据,就不需要同步。这种技术称为线程封闭,它是实现线程安全的最简单方式之一。 在 Swing 中大量使用了线程封闭技术。Swing 的可视化组件和数据模型对象都不是线程安全的,Swing 通过将它们封闭到 Swing 的事件分发线程中来实现线程安全性。 (查看原文)
    红色有角F叔 8回复 2014-05-09 00:00:28
    —— 引自章节:线程封闭
  • 线程封闭技术的另一种常见应用是 JDBC 的 Connection 对象。JDBC 规范并不要求 Connection 对象必须是线程安全的。在典型的服务器应用程序中,线程从连接池中获得一个 Connection 对象,并且用该对象来处理请求,使用完后再将对象返还给连接池。... 这种连接管理模式在处理请求时隐含地将 Connection 对象封闭在线程中。 (查看原文)
    红色有角F叔 8回复 2014-05-09 00:00:28
    —— 引自章节:线程封闭
  • 正如阻塞队列适用于生产者-消费者模式,双端队列同样适用于另一种相关模式,即工作密取(Work Stealing)。在生产者-消费者设计中,所有消费者有一个共享的工作队列,而在工作密取设计中,每个消费者都有各自的双端队列。如果一个消费者完成了自己的双端队列中的全部工作,那么它可以从其它消费者双端队列末尾秘密地获取工作。密取工作模式比传统的生产者-消费者模式具有更高的可伸缩性,这是因为工作者线程不会在单个共享的任务队列上发生竞争。在大多数时候,它们都只是访问自己的双端队列,从而极大地减小了竞争。当工作者线程需要访问另一个队列时,它会从队列的尾部而不是头部获取工作,因此进一步降低了队列上的竞争程度。 工作密取非常适用于既是消费者也是生产者问题—当执行某个工作时可能导致出现更多的工作。例如,在网页爬虫程序在处理一个页面时,通常会发现有更多的页面需要处理。 (查看原文)
    红色有角F叔 5回复 2014-05-14 10:24:53
    —— 引自章节:双端队列和工作密取
<前页 1 2 3 4 后页>