`

初学Java多线程:使用Synchronized块同步变量

阅读更多

我们可以通过synchronized块来同步特定的静态或非静态方法。要想实现这种需求必须为这些特性的方法定义一个类变量,然后将这些方法的代码用synchronized块括起来,并将这个类变量作为参数传入synchronized块。下面的代码演示了如何同步特定的类方法:

package com.jelly.thread;
/**
 * 
 * @author Jelly QQ:136179492
 *
 */
public class SyncThread extends Thread {
	private static String sync = "";
	private String methodType = "";

	public static void method(String s) {
		synchronized (sync) {
			sync = s;
			System.out.println(s);
			while (true)
				;
		}
	}

	public void method1() {
		method("method1");
	}

	public static void staticmethod1() {
		method("staticmethod1");
	}

	public void run() {
		if (methodType.equals("static")) {
			staticmethod1();
		} else if (methodType.equals("nonstatic"))
			method1();
	}

	public SyncThread(String methodType) {
		this.methodType = methodType;
	}

	public static void main(String[] args) {
		SyncThread sample1 = new SyncThread("nonstatic");
		SyncThread sample2 = new SyncThread("static");
		sample1.start();
		sample2.start();
	}

}

 


运行结果如下:

method1
staticMethod1

看到上面的运行结果很多读者可能感到惊奇。在上面的代码中method1和staticMethod1方法使用了静态字符串变量sync进行同步。这两个方法只能有一个同时执行,而这两个方法都会执行014行的无限循环语句。因此,输出结果只能是method1和staticMethod1其中之一。但这个程序将这两个字符串都输出了。

出现这种结果的愿意很简单,我们看一下012行就知道了。原来在这一行将sync的值改变了。在这里要说一下Java中的String类型。String类型和Java中其他的复杂类型不同。在使用String型变量时,只要给这个变量赋一次值,Java就会创建个新的String类型的实例。如下面的代码所示:

  1. String s =  "hello" ;  
  2. System.out.println(s.hashCode());  
  3. s =  "world" ;  
  4. System.out.println(s.hashCode());   

在上面的代码中。第一个s和再次赋值后的s的hashCode的值是不一样的。由于创建String类的实例并不需要使用new,因此,在同步String类型的变量时要注意不要给这个变量赋值,否则会使变量无法同步。

由于在013行已经为sync创建了一个新的实例,假设method1先执行,当method1方法执行了013行的代码后,sync的值就已经不是最初那个值了,而method1方法锁定的仍然是sync变量最初的那个值。而在这时,staticMethod1正好执行到synchronized(sync),在staticMethod1方法中要锁定的这个sync和method1方法锁定的sync已经不是一个了,因此,这两个方法的同步性已经被破坏了。

解决以上问题的方法当然是将013行去掉。在本例中加上这行,只是为了说明使用类变量来同步方法时如果在synchronized块中将同步变量的值改变,就会破坏方法之间的同步。为了彻底避免这种情况发生,在定义同步变量时可以使用final关键字。如将上面的程序中的005行可改成如下形式:

  1. private   final   static  String sync =  "" ;  

使用final关键字后,sync只能在定义时为其赋值,并且以后不能再修改。如果在程序的其他地方给sync赋了值,程序就无法编译通过。在Eclipse等开发工具中,会直接在错误的地方给出提示。

我们可以从两个角度来理解synchronized块。如果从类方法的角度来理解,可以通过类变量来同步相应的方法。如果从类变量的角度来理解,可以使用synchronized块来保证某个类变量同时只能被一个方法访问。不管从哪个角度来理解,它们的实质都是一样的,就是利用类变量来获得同步锁,通过同步锁的互斥性来实现同步。

注意:在使用synchronized块时应注意,synchronized块只能使用对象作为它的参数。如果是简单类型的变量(如int、char、boolean等),不能使用synchronized来同步。

分享到:
评论

相关推荐

    java多线程的讲解和实战

    8. **并发集合类**:Java提供了并发安全的集合类,如`ConcurrentHashMap`, `CopyOnWriteArrayList`, `BlockingQueue`等,它们内部实现了线程安全的算法,可以在多线程环境下高效使用。 9. **线程中断**:`interrupt...

    Java多线程初学者指南

    Java多线程初学者指南是一份详尽的教育资源,涵盖了多线程编程的基本概念和实践技巧,适合初学者深入理解这一重要技术。本指南通过12篇文档,逐步引导学习者掌握Java多线程的核心知识。 首先,让我们从基础开始,...

    Java多线程详解(超详细)_狂神说笔记完整版_项目代码_适合小白随课程学习

    本教程将详细讲解Java中的多线程概念,包括线程的创建、状态、同步以及高级主题,旨在帮助初学者逐步掌握这一关键技能。 1. **线程简介** - 线程是操作系统分配CPU时间的基本单位,一个进程可以有多个线程,它们...

    java多线程简单下载器

    【Java多线程简单下载器】是一个初学者的编程作业,虽然代码可能较为混乱,但其核心功能已经实现,即通过多线程技术进行文件的下载。在Java中,多线程是并发处理的重要手段,它允许多个任务在同一时间执行,从而提高...

    Java多线程文档

    4. wait()、notify()与notifyAll():这三个方法用于线程间的通信,但必须在同步块或同步方法中使用,否则会抛出异常。 四、线程池 Java提供了ExecutorService接口和ThreadPoolExecutor类来管理线程池,可以有效控制...

    java多线程并发实战和源码

    本书主要聚焦于Java多线程的基础理论和实际应用,虽然书中实例和源码相对较少,但仍然能够为初学者提供一个良好的起点,了解多线程的基本概念和常见模式。 首先,Java多线程的核心概念包括线程的创建、启动、同步和...

    java多线程案例——未完成

    Java多线程是Java编程中的一个重要领域,它允许程序同时执行多个任务,从而提高系统效率和资源利用率。在这个未完成的案例中,我们可能正在探讨如何...对于初学者来说,理解并掌握这些概念是成为Java多线程专家的基础。

    深入浅出Java多线程.pdf

    - **Thread 类**:Java 中实现多线程的主要方式之一,继承自 Object 类,实现了 Runnable 接口。 - **Runnable 接口**:实现此接口以定义线程的任务,通常与 Thread 类结合使用。 - **Callable & Future**:提供了...

    JAVA 多线程的两点误区

    总结来说,Java多线程编程中存在许多常见的误区,尤其是对于初学者而言。正确理解线程的启动与执行状态、掌握线程间的数据共享与同步机制是非常关键的。希望以上内容能够帮助大家更好地理解和应用Java多线程技术。

    java课程设计线程同步五子棋.zip

    1. **同步块(Synchronized Block)**:使用`synchronized`关键字包围代码块,确保同一时间只有一个线程可以执行该代码。在这个五子棋游戏中,可能在落子操作或者检查胜负的函数中使用了同步块,防止两个线程同时...

    java多线程的应用事例

    本文将深入探讨Java多线程的应用实例,这对于初学者来说是一个很好的学习起点。 首先,我们来看"SimulateRailwayStation.java"这个文件名,它很可能包含了一个火车站模拟的示例。在实际场景中,火车站通常有多项...

    Java 线程同步调用

    Java线程同步调用是多线程编程中的基石,它通过同步方法和同步代码块两种方式,有效地控制了线程之间的交互,防止了多线程环境下常见的并发问题。无论是对于初学者还是有经验的开发者,掌握和熟练应用这些同步机制都...

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

    在Java编程中,多线程是一项关键技能,它允许程序同时执行多个任务,提升系统效率。这个名为"Java多线程的小例子——吃包子"的示例...这个示例是一个生动的教学工具,能够帮助初学者更好地理解和运用Java的多线程技术。

    Java多线程的总结

    通过以上内容,初学者可以对Java多线程有一个全面的认识,理解线程的基本概念、创建方式、同步控制以及并发管理。随着实践经验的积累,深入学习线程池的使用、线程安全的高级主题以及Java并发API,将进一步提升在多...

    张孝祥Java多线程与并发库高级应用笔记

    ### 张孝祥Java多线程与并发库高级应用笔记概览 #### 一、Java多线程技术的重要性与挑战 Java线程技术是软件工程领域不可或缺的一部分,尤其在底层编程、Android应用开发以及游戏开发中,其重要性不言而喻。然而,...

    java多线程设计模式详解(PDF及源码)

    总之,《Java多线程设计模式详解》是一本全面且实用的指南,无论你是Java初学者还是经验丰富的开发者,都能从中受益,提升你的多线程编程技巧。通过学习这本书,你可以更好地驾驭Java的多线程世界,编写出高效、稳定...

    Java多线程编程核心+带目录版

    《Java多线程编程核心技术》是一本由资深Java专家倾力打造的专业著作,结合了作者10年的实战经验,深入浅出地解析了Java多线程编程的核心概念和技术。本书以丰富的案例为引导,旨在帮助读者全面理解和掌握Java平台上...

    [从初学到精通系列:Java从初学到精通].辛立伟等.扫描版

    根据提供的文件信息,我们可以推断出这是一本关于Java编程语言的学习资料——《从初学到精通系列:Java从初学到精通》,作者为辛立伟等人。本书旨在帮助读者从零基础开始逐步掌握Java编程技术,并最终达到精通的程度...

Global site tag (gtag.js) - Google Analytics