`
wuhongyu
  • 浏览: 406938 次
  • 性别: Icon_minigender_1
  • 来自: 哈尔滨
社区版块
存档分类
最新评论

JAVA 线程学习笔记--同步

阅读更多

为了确保可以在线程之间以受控方式共享数据,Java 语言提供了两个关键字:synchronized 和volatile。

 

Synchronized 有两个重要含义:它确保了一次只有一个线程可以执行代码的受保护部分(互斥,mutual exclusion 或者说 mutex),而且它确保了一个线程更改的数据对于其它线程是可见的(更改的可见性)。
Volatile 比同步更简单,只适合于控制对基本变量(整数、布尔变量等)的单个实例的访问。当一个变量被声明成 volatile,任何对该变量的写操作都会绕过高速缓存,直接写入主内存,而任何对该变量的读取也都绕过高速缓存,直接取自主内存。这表示所有线程在任何时候看到的 volatile 变量值都相同。

 

Synchronized :

    每个 Java 对象都有一个相关的锁。同一时间只能有一个线程持有 Java 锁。当线程进入 synchronized 代码块时,线程会阻塞并等待,直到锁可用,当它可用时,就会获得这个锁,然后执行代码块。当控制退出受保护的代码块时,即到达了代码块末尾或者抛出了没有在 synchronized 块中捕获的异常时,它就会释放该锁。
    需要注意的是,无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或函数当作锁。但即使一个 Java 对象的锁正被其他线程占用时,仍可访问这个对象中没有 synchronized 修饰的代码块。


假设多个线程共享一个计数器,如下:
public class Counter {
   private int counter = 0;
   public int get() { return counter; }
   public void set(int n) { counter = n; }
   public void increment() {
      set(get() + 1);
   }
}


    要使递增操作正确运行,不仅get() 和 set() 必须是 synchronized,而且 increment() 也必需是synchronized!否则,调用 increment() 的线程可能会中断另一个调用 increment() 的线程。如果不走运,最终结果将会是计数器只增加了一次,不是两次。同步 increment() 防止了这种情况的发生,因为整个递增操作是原子的。

 

synchronized作用于方法时,锁定的是调用这个同步方法对象。当一个对象P1在不同的线程中执行这个同步方法时,它们之间会形成互斥,达到同步的效果。但是这个对象所属的Class所产生的另一对象P2却可以任意调用这个被加了synchronized关键字的方法。

 

public class TestSynchronized extends Thread{

    public synchronized void method(){
            System.out.println(this.currentThread().getName() + " - method() begin");
            try {
                    Thread.sleep(20000);
            } catch (InterruptedException e) {
                    e.printStackTrace();
            }
            System.out.println(this.currentThread().getName() + " - method() over");
    }

    public void run() {
            method();
    }
   
    public static void main(String[] args) {
        /*
         * 同一个对象:
         * 当同一个对象在不同的线程中,执行一个同步方法时,它们之间会形成互斥,达到同步的效果
         */
        TestSynchronized ts = new TestSynchronized();
        Thread t1 = new Thread(ts);
        Thread t2 = new Thread(ts);
        t1.start();
        t2.start();
       
           
        /*
         * 不同的对象:
         * 当同一个Class产生的不同对象在不同的线程中执行一个同步方法时,
         * 他们可以任意调用这个被加了synchronized关键字的方法,而互不影响,不形成互斥,达不到同步效果。
         * 也就是说此时synchronized并未起到任何作用,与不加这个关键字效果是一样的。
         *
        TestSynchronized ts1 = new TestSynchronized();
        TestSynchronized ts2 = new TestSynchronized();
        Thread t1 = new Thread(ts1);
        Thread t2 = new Thread(ts2);
        t1.start();
        t2.start();
        */
    }
}

同一个对象的运行结果:
Thread-1 - method() begin
Thread-1 - method() over
Thread-2 - method() begin
Thread-2 - method() over

不同的对象的运行结果:
Thread-1 - method() begin
Thread-2 - method() begin
Thread-1 - method() over
Thread-2 - method() over

 

其中,

public synchronized void method(){
        ......
 }
相当于
public synchronized void method(){
         synchronized (this){ //this指的就是调用这个方法的对象
            ......
         }
 }

 

synchronized作用于同步块时,示例代码如下:
public void method(SomeObject so)
{
  synchronized(so)
  {
   //…..
 }
}


  这时,锁就是so这个对象,谁拿到这个锁谁就可以运行它所控制的那段代码。当有一个明确的对象作为锁时,就可以这样写程序,但当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的instance变量(它得是一个对象)来充当锁:


  class Foo implements Runnable
  {
    private byte[] lock = new byte[0]; // 特殊的instance变量
    Public void method()
    {
      synchronized(lock) { //… }
    }
   //…..
  }
  注:零长度的byte数组对象创建起来将比任何对象都经济――查看编译后的字节码:生成零长度的byte[]对象只需3条操作码,而Object lock = new Object()则需要7行操作码。

分享到:
评论
1 楼 dngoryaner 2011-09-15  
[color=red][/color][size=xx-large][/size][align=center][/align]

相关推荐

    java线程学习笔记

    Java 线程学习笔记 Java 线程创建有两种方法: 1. 继承 Thread 类,重写 run 方法:通过继承 Thread 类并重写 run 方法来创建线程,这种方法可以使线程具有自己的执行逻辑。 2. 实现 Runnable 接口:通过实现 ...

    JAVA 多线程学习笔记

    这篇学习笔记将深入探讨Java多线程的核心概念、实现方式以及相关工具的使用。 一、多线程基础 1. 线程与进程:在操作系统中,进程是资源分配的基本单位,而线程是程序执行的基本单位。每个进程至少有一个主线程,...

    java学习笔记-html-ssh-js

    【Java学习笔记】 在Java的学习旅程中,深入理解其核心概念是至关重要的。Java是一种广泛使用的面向对象的编程语言,以其跨平台性、高效性和稳定性而受到青睐。本笔记集合将带你逐步走进Java的世界,从基础语法到...

    java学习笔记-初学者的福音

    这份"java学习笔记-初学者的福音"涵盖了从基础到进阶的多种概念,旨在帮助初学者系统地掌握Java编程。 首先,Java的基础部分包括语法结构。Java是一种面向对象的语言,这意味着它将数据和操作数据的方法封装在类中...

    2022年Java学习笔记-Java课程配套案例.rar

    这份"2022年Java学习笔记-Java课程配套案例.rar"压缩包文件显然是为了帮助学习者深入理解Java编程,通过实践案例来巩固理论知识。下面将详细探讨Java语言的一些核心知识点,并结合压缩包中的案例进行说明。 1. **...

    多线程学习笔记

    多线程学习笔记 iOS开发中,多线程是一种常见的技术手段,用于优化应用程序的性能,提升用户体验。多线程的核心是让程序能够并发地执行多个任务,合理地利用设备的计算能力,尤其是在拥有多个核心的处理器上。 ...

    Java多线程学习笔记

    ### Java多线程学习笔记 #### 一、线程的基本概念 在计算机科学中,**线程**(Thread)是程序执行流的最小单位。一个标准的程序只能做一件事情,而通过多线程技术,可以让程序同时处理多个任务。在Java中,线程是...

    良葛格 Java 学习笔记-JavaGossip全(v1+v2)

    《良葛格 Java 学习笔记-JavaGossip全(v1+v2)》是一部集成了作者良葛格多年编程经验的学习资料,旨在帮助初学者和有经验的开发者深入理解和掌握Java这门强大的编程语言。这份笔记包含了JavaGossip的两个版本,v1和...

    Java基础 学习笔记 Markdownr版

    4. 多线程:在10多线程.md中,介绍了如何创建和管理Java线程,包括Thread类、Runnable接口,以及同步机制如synchronized关键字、wait()、notify()和notifyAll()方法。多线程技术是实现并发执行的关键,有助于提高...

    JAVA并发编程实践-线程安全-学习笔记

    除了synchronized,Java还提供了其他同步机制,如volatile变量,它能确保对变量的修改对所有线程都是可见的,但不保证原子性。另外,Java的并发包`java.util.concurrent`引入了显式锁(如`Lock`接口及其实现类),...

    JAVA并发编程实践-线程执行-学习笔记

    占式线程调度是Java和大多数现代操作系统采用的线程调度策略。在这种模式下,操作系统决定何时以及哪个线程将获得CPU的执行时间。线程的执行不是由线程自身控制,而是由操作系统通过时间片轮转或者优先级调度等方式...

    java多线程笔记

    Java线程是多任务编程的重要组成部分,它允许程序同时执行多个独立的代码片段,从而提高程序的效率和响应性。本文将深入探讨Java线程的概念、原理以及如何在实际编程中进行有效管理。 首先,我们要了解操作系统中的...

    java学习笔记-老师的课程笔记

    Java学习笔记是初学者探索Java编程世界的宝贵资源。这份由老师精心整理的课程笔记涵盖了Java的基础到进阶知识,旨在帮助新手快速理解并掌握这门强大的面向对象编程语言。笔记内容可能包括但不限于以下方面: 一、...

    Java 学习笔记Java学习笔记

    Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems(现为Oracle公司的一部分)于1995年发布。...Java学习笔记涵盖了这些核心知识点,通过深入学习和实践,你可以逐步掌握Java编程,并应用于实际项目开发中。

    java笔记--

    本笔记将深入探讨Java的基础知识和核心概念。 1. **Java基础** - **语法**:Java语法与C++类似,但更加简洁。例如,Java使用垃圾回收机制自动管理内存,避免了C++中的内存泄漏问题。 - **类与对象**:Java是面向...

    bjy学习笔记-阿里巴巴Java编码规范以及一些技术笔记

    在本压缩包“bjy学习笔记-阿里巴巴Java编码规范以及一些技术笔记”中,我们可以预见到包含的内容主要是关于Java编程语言的学习心得,特别是遵循阿里巴巴的Java编码规范的相关知识。这是一份宝贵的资源,对于Java...

    java从入门到精通学习笔记-Lesson5(多线程).pdf

    Java 多线程是编程中的重要概念,尤其在并发处理和高效系统设计中扮演着关键角色。本节主要探讨了Java中的线程概念以及如何创建...通过不断的实践和学习,可以更好地利用Java的多线程特性来提升软件的性能和用户体验。

    java学习笔记markdown

    6. **多线程**:阐述Java中的并发编程,包括线程的创建、同步机制(synchronized、wait/notify、Lock接口)、线程池以及并发集合。 7. **设计模式**:介绍常见的设计模式,如单例、工厂、装饰器、观察者等,帮助...

Global site tag (gtag.js) - Google Analytics