`

多线程——同步(synchronized)上

    博客分类:
  • java
阅读更多

多线程——同步(synchronized)上

 

多线程编程中,最关键、最关心的问题应该就是同步问题,这是一个难点,也是核心。

从jdk最早的版本的synchronized、volatile,到jdk 1.5中提供的java.util.concurrent.locks包中的Lock接口(实现有ReadLock,WriteLock,ReentrantLock),多线程的实现也是一步步走向成熟化。

 

同步,它是通过什么机制来控制的呢?第一反应就是锁,这个在学习操作系统与数据库的时候,应该都已经接触到了。在Java的多线程程序中,当多个程序竞争同一个资源时,为了防止资源的腐蚀,给第一个访问资源的线程分配一个对象锁,而后来者需要等待这个对象锁的释放。

 

是的,Java线程的同步,最关心的是共享资源的使用。

 

先来了解一些有哪些线程的共享资源,

从JVM中了解有哪些线程共享的数据是需要进行协调:

1,保存在堆中的实例变量;2,保存在方法区的类变量。

 

而在Java虚拟机加载类的时候,每个对象或类都会与一个监视器相关联,用来保护对象的实例变量或类变量;当然,如果对象没有实例变量,或类没有变量,监视器就什么也不监视了。

 

为了实现上面的说的监视器的互斥性,虚拟机为每一个对象或类都关联了一个锁(也叫隐形锁),这里说明一下,类锁也是通过对象锁来实现的,因为在类加载的时候,JVM会为每一个类创建一个java.lang.Class的一个实例;所以当锁对对象的时候,也就锁住这个类的类对象。

 

另外,一个线程是可以对一个对象进行多次上锁,也就对应着多次释放;它是通过JVM为每个对象锁提供的lock计算器,上一次锁,就加1,对应的减1,当计算器的值为0时,就释放。这个对象锁是JVM内部的监视器使用的,也是由JVM自动生成的,所有程序猿就不用自己动手来加了。

 

介绍完java的同步原理后,我们进入正题,先来说说synchronized的使用,而其它的同步,将在后面的章节中介绍。

 

先来运行一个例子试试。

package thread_test;

/**
 * 测试扩展Thread类实现的多线程程序 
 * 
 * @author ciding 
 * @createTime Dec 7, 2011 9:37:25 AM
 *
 */
public class TestThread extends Thread{ 
	private int threadnum;

	public TestThread(int threadnum) { 
		this.threadnum = threadnum; 
	}
	
	@Override
	public synchronized void run() { 
		for(int i = 0;i<1000;i++){ 
	        		System.out.println("NO." + threadnum + ":" + i );
		}
    	} 
	
    	public static void main(String[] args) throws Exception { 
    		for(int i=0; i<10; i++){
        			new TestThread(i).start();
        			Thread.sleep(1);
    		}
    	} 
}

 

运行结果:

NO.0:887
NO.0:888
NO.0:889
NO.0:890
NO.0:891
NO.0:892
NO.0:893
NO.0:894
NO.7:122
NO.7:123
NO.7:124

上面只是一个片段,说明一个问题而已。

细心的童鞋会发现,NO.0:894后面是NO.7:122,也就是说没有按照从0开始到999。

都说synchronized可以实现同步方法或同步块,这里怎么就不行呢?

 

先从同步的机制来分析一下,同步是通过锁来实现的,那么上面的例子中,锁定了什么对象,或锁定了什么类呢?里面有两个变量,一个是i,一个是threadnum;i是方法内部的,threadnum是私有的。

再来了解一下synchronized的运行机制:

      在java程序中,当使用synchronized块或synchronized方法时,标志这个区域进行监视;而JVM在处理程序时,当有程序进入监视区域时,就会自动锁上对象或类。

 

那么上面的例子中,synchronized关键字用上后,锁定的是什么呢?

当synchronized方法时,锁定调用方法的实例对象本身做为对象锁。本例中,10个线程都有自己创建的TestThread的类对象,所以获取的对象锁,也是自己的对象锁,与其它线程没有任何关系。

 

要实现方法锁定,必须锁定有共享的对象。

 

对上面的实例修改一下,再看看:

package thread_test;

/**
 * 测试扩展Thread类实现的多线程程序 
 * 
 * @author ciding 
 * @createTime Dec 7, 2011 9:37:25 AM
 *
 */
public class TestThread extends Thread{ 
	private int threadnum;
	private String flag;	//标记
	
	public TestThread(int threadnum,String flag) { 
       		 this.threadnum = threadnum; 
        		this.flag = flag;
    	}
	
	@Override
    	public void run() { 
		synchronized(flag){
			for(int i = 0;i<1000;i++){ 
	            			System.out.println("NO." + threadnum + ":" + i );
	        		} 
		}
    	} 

    	public static void main(String[] args) throws Exception { 
    		String flag = new String("flag");
    		for(int i=0; i<10; i++){
        			new TestThread(i,flag).start();
        			Thread.sleep(1);
    		}
    	} 
}

 

也就加了一个共享的标志flag。然后在通过synchronized块,对flag标志进行同步;这就满足了锁定共享对象的条件。

是的,运行结果,已经按顺序来了。

 

 

一下写的太多,先休息一下,下一节再补上synchronized的使用下

 多线程——同步(synchronized)下

 

 

 

 Java多线程及线程池专题 汇总

 http://ciding.iteye.com/blog/1300110

  

6
3
分享到:
评论
4 楼 ciding 2011-12-29  
helloqyq 写道
我这还是不行啊!楼主!

什么不行呢???

不知道是指哪地方有问题,不行。
3 楼 helloqyq 2011-12-29  
我这还是不行啊!楼主!
2 楼 ciding 2011-12-13  
单纯的实现上面的功能,肯定是可以的,只要锁定了共享的对象就可以
TestThread.class,锁定的是类对象。

接着往后面看,应该还有些收获。
1 楼 255777 2011-12-13  
不用flag标志,可以换成synchronized(TestThread.class)也可以

相关推荐

    Java多线程——线程八锁案例分析.docx

    在实际开发中,理解并熟练掌握这些线程同步机制对于构建高效且稳定的多线程应用程序至关重要。除了`synchronized`关键字,Java还提供了其他并发控制工具,如`java.util.concurrent`包下的`Semaphore`、`Lock`接口...

    JAVA多线程——一篇文章让你彻底征服多线程开发.docx

    ### JAVA多线程详解 #### 一、线程与进程的概念 在计算机科学中,**进程**是指一个正在运行的应用程序或程序实例,而**线程**则是进程中可并发执行的一部分,是进程内的一个执行流。一个进程可以拥有多个线程,这些...

    多线程编程——实战篇

    接下来我们将通过一个具体的例子——“厨师-食客”模式来深入理解多线程编程的实际应用。 1. **模型介绍**: - 生产者(厨师):负责制作食物,并将其放入共享的“仓库”(桌子)。 - 消费者(食客):从“仓库”...

    java多线程教程——一个课件彻底搞清多线程

    本教程将深入讲解Java线程的相关知识,包括进程与线程的基本概念、线程的创建和启动、多线程的互斥与同步、线程状态和线程控制以及死锁的概念。 首先,我们要理解进程与线程的区别。进程是操作系统资源分配的基本...

    java 多线程同步方法的实例

    在Java编程语言中,多线程同步是一种控制多个线程并发执行的重要机制,它确保了共享资源的安全访问,防止数据不一致性和竞态条件的发生。本文将深入探讨Java中的多线程同步方法,并通过实例来阐述其工作原理。 首先...

    线程——基本线程的应用和线程调用控件

    - 线程同步与互斥:为了防止线程间的竞态条件,可以使用锁(如Java的`synchronized`关键字,C#'s `Monitor`类)或其他同步机制。 4. **线程调度**: - 线程调度器负责决定哪个线程应该获得CPU执行权。调度策略...

    java多线程案例——未完成

    Java多线程是Java编程中的一个重要领域,它允许程序同时执行多个任务,从而提高系统效率和资源利用率。在这个未完成的案例中,我们可能正在探讨如何在Java中创建和管理线程,以及处理多线程环境下的并发问题。下面是...

    操作系统实验 多线程同步与互斥 java编写 有界面

    操作系统实验是计算机科学教育中的重要组成部分,它帮助学生理解和掌握操作系统的基本原理,特别是多线程同步与互斥的概念。在Java编程环境下,这些概念可以通过实际的代码实现来深入理解。 多线程是现代操作系统中...

    文件复制——多线程

    综上所述,文件复制的多线程实现涉及了编程语言的线程模型、文件操作、同步机制、性能优化以及错误处理等多个方面。通过学习和实践这些知识,开发者能够构建出高效且稳定的文件复制工具,提高系统的工作效率。如果...

    Java多线程的小例子——吃包子

    这个名为"Java多线程的小例子——吃包子"的示例,旨在帮助开发者直观地理解多线程的工作原理。下面我们将深入探讨该示例所涉及的核心知识点。 首先,多线程通常涉及到以下几个关键概念: 1. **线程(Thread)**:...

    JAVA项目——多线程下载代码

    本项目以"JAVA项目——多线程下载代码"为主题,使用Eclipse集成开发环境进行实现,适合于Java初学者或毕业设计实践。下面我们将深入探讨相关的Java多线程下载知识点。 1. **线程基础**:在Java中,线程是程序执行的...

    Java多线程同步机制在售票系统的实现

    本文旨在通过分析一个具体的案例——长途汽车售票系统的多线程同步机制实现,来探讨如何利用Java的多线程技术解决实际问题。 #### 二、多线程的基本概念 ##### 2.1 线程与进程的主要区别 1. **划分粒度**:线程的...

    第13章龟兔赛跑——多线程.ppt

    总结来说,通过学习"第13章龟兔赛跑——多线程",我们可以掌握Java中多线程的基本概念、创建和管理,以及如何利用多线程提高程序效率。理解并熟练应用这些知识对于开发高效、响应迅速的软件至关重要。

    Java——多线程编程技术.pdf

    Java多线程编程技术的同步机制是通过Synchronized关键字和Volatile关键字来实现的。Synchronized关键字可以使线程之间同步执行,而Volatile关键字可以使线程之间共享变量。 Java多线程编程技术的应用场景非常广泛,...

    IOS应用源码——多线程.zip

    本资源“IOS应用源码——多线程.zip”包含了一个具体的iOS应用实例,用于展示如何在项目中实现多线程技术。通过分析这个源码,开发者可以深入理解多线程在iOS中的应用。 首先,我们要了解iOS中的多线程模型。iOS...

    面试题解惑系列(十)——话说多线程

    理解和掌握多线程是Java开发者必备的技能之一,不仅要在理论层面上理解并发和线程的概念,还需要熟悉Java提供的各种线程同步机制和线程池的使用,以便在实际开发中解决并发问题,提高程序的稳定性和效率。...

    Java练手小项目——多线程聊天室.zip

    【Java练手小项目——多线程聊天室】 在Java编程世界中,多线程是不可或缺的一部分,尤其在开发实时性、交互性强的应用时,如我们的主题“多线程聊天室”。这个实战项目旨在帮助开发者深入理解Java多线程的概念,并...

    JAVA多线程同步机制及其应用.doc

    本文档详细介绍了Java中多线程的相关概念、创建方式、线程管理、同步机制以及一个实际的应用案例——交通灯管理系统。 首先,线程是程序执行的最小单元,一个进程可以包含多个线程。在Java中,创建线程有两种主要...

    多线程面试题

    在Java编程领域,多线程是面试中常见且重要的知识点,尤其对于系统设计和高并发处理的岗位至关重要。本文将围绕“多线程面试题”这一主题,深入探讨相关概念、技术及其应用。 1. **线程的概念**:线程是程序执行的...

    JAVA内存模型——同步操作规则1

    它为多线程环境下如何保证数据一致性提供了理论基础。下面将详细阐述标题和描述中涉及的同步操作规则: 1. **顺序执行规则**: Read和Load操作必须先于Store和Write操作发生,这意味着在获取数据(Read/Load)之后...

Global site tag (gtag.js) - Google Analytics