`

Java 多线程例子6 线程安全 线程同步 同步代码块 同步函数

阅读更多

线程安全

出现线程安全就是在使用多线程的时候程序出现了不期望的结果。

怎样思考线程安全:线程中任何一步运行完都可能交出CPU的控制权。

下面是一个可能出现线程安全的例子:

class ThreadDemo {
	public static void main(String[] args) {
		TestThread t = new TestThread();
		new Thread(t).start();
		new Thread(t).start();
		new Thread(t).start();
		new Thread(t).start();
	}
}

class TestThread implements Runnable {
	int tickets = 100;
	public void run() {
		while(true) {
			if(tickets<=0)
				break;
			//try{Thread.sleep(10);}catch(Exception e) {}
			System.out.println(Thread.currentThread().getName() 
				+ " is saling " + tickets--);
		}
	}
}

 例子展示了四个售票员一起卖这100张票,那么卖出同样序号的票是我们不期望看到了情况吧,上面已经提到了,分析线程安全的最基本的方法就是认为线程运行的时候任何情况下都可以交出CPU的控制权,上面一共启动了4个线程,现在假设tickets的值为1时,线程1在运行完“if(tickets<=0)”后交出CPU,后线程2得到了CPU,卖出了票1,后线程1重新得到了CPU,又卖出了票1或0。当然,上述情况是我们假设在什么情况下会出现象这样的线程安全的问题,在一般情况,我们运行这个程序好几次也不能看出这样的线程安全问题,那我们怎么确定这个问题呢?我们可以用“sleep(100)”来主动交出CPU来验证我们的想法:去掉上面注释的sleep再运行程序,得到

运行结果 写道
Thread-1 is saling 2
Thread-2 is saling 1
Thread-3 is saling 0
Thread-0 is saling -1
Thread-1 is saling -2

 

卖出了0、-1和-2的票,证明上述这种写法是存在线程安全的。

线程同步

为了解决线程安全的问题,就要引入线程同步。

class ThreadDemo {
	public static void main(String[] args) {
		TestThread t = new TestThread();
		new Thread(t).start();
		new Thread(t).start();
		new Thread(t).start();
		new Thread(t).start();
	}
}

class TestThread implements Runnable {
	int tickets = 100;
	String str = "";
	public void run() {
		while(true) {
			synchronized(str) {
				if(tickets<=0)
					break;
				//try{Thread.sleep(10);}catch(Exception e) {}
				System.out.println(Thread.currentThread().getName() 
					+ " is saling " + tickets--);
			}
		}
	}
}

 在上面的代码中加入synchronized,就可以实现线程同步了。

运行结果 写道
hread-2 is saling 5
hread-3 is saling 4
hread-1 is saling 3
hread-0 is saling 2
hread-2 is saling 1

 

这个线程同步怎么理解呢?这里有个锁旗标的概念,锁旗标可以理解为java中的每一个对象都有个标志位,该标志位开始的状态是1,当执行完synchronized后这个对象的标志位被置为了0,这个过程就说这个线程得到了这个对象的锁旗标,synchronized块运行完之后这个线程会让出这个对象的锁旗标,而每个线程在遇到synchronized是都回查看这个对象的锁旗标在不在,如果不在该线程就会主要让出CPU。

这里还要记住synchronized的对象一定要是多个线程的公共对象,要是各自的对象就不能实现同步了。如下面改变str定义的位置。

class ThreadDemo {
	public static void main(String[] args) {
		TestThread t = new TestThread();
		new Thread(t).start();
		new Thread(t).start();
		new Thread(t).start();
		new Thread(t).start();
	}
}

class TestThread implements Runnable {
	int tickets = 100;
	public void run() {
		String str = "";
		while(true) {
			synchronized(str) {
				if(tickets<=0)
					break;
				//try{Thread.sleep(10);}catch(Exception e) {}
				System.out.println(Thread.currentThread().getName() 
					+ " is saling " + tickets--);
			}
		}
	}
}

 

结果为 写道
Thread-1 is saling 2
Thread-2 is saling 1
Thread-3 is saling 0
Thread-0 is saling -1
Thread-1 is saling -2

 另外,在运行加入了synchronized同步块的程序的时会发现速度明显比没有同步块的程序要慢的多,所以在确定不会出现线程安全问题的程序中不要加入同步块,就像我们经常先使用Vector还是有ArrayList呢?它们两个的功能基本是完全一样的都是List,而Vector中的函数考虑了线程同步,ArrayList没有,这下就非常明显了,如果需要保证线程安全是就用Vector,不需要就用ArrayList效率高些。

同步函数

同步函数实现

class ThreadDemo {
	public static void main(String[] args) {
		TestThread t = new TestThread();
		new Thread(t).start();
		new Thread(t).start();
		new Thread(t).start();
		new Thread(t).start();
	}
}

class TestThread implements Runnable {
	int tickets = 100;
	public void run() {
		while(true) {
			sale();
		}
	}
	public synchronized void sale() {
		if(tickets<=0)
				return;
		try{Thread.sleep(10);}catch(Exception e) {}
		System.out.println(Thread.currentThread().getName() 
					+ " is saling " + tickets--);
	}
}

 同步函数实际上同步的是this对象,这样如果要想某一个同步块和一个同步函数同步,就在同步块中使用this对象。

分享到:
评论
1 楼 wpf523 2014-07-14  
mark

相关推荐

    Java多线程机制(讲述java里面与多线程有关的函数)

    Java提供了synchronized关键字来实现方法或代码块的同步,防止多个线程同时访问同一块代码。 9.7 在同步方法中使用wait(), notify和notifyAll(): 这些方法用于线程间通信。wait()使当前线程进入等待状态,直到收到...

    java多线程的讲解和实战

    本资料详细讲解了Java多线程的原理,并提供了丰富的实战代码,非常适合Java初学者以及希望深入理解多线程的开发者。 1. **线程的基本概念**:线程是程序执行的最小单位,一个进程中可以有多个线程同时运行。Java...

    Java多线程实例代码

    Java多线程是Java编程中的重要概念,它允许程序同时执行多个任务,提高了程序的效率和响应性。在Java中,实现多线程有两种主要方式:通过继承`Thread`类和实现`Runnable`接口。 1. 继承Thread类: 当你需要创建一...

    java多线程编程-详细炒作例子

    ### Java多线程编程详解与实战案例 ...然而,线程的管理和调度也带来了同步、死锁等挑战,因此在享受多线程带来的好处的同时,也需要谨慎地处理线程间的通信和资源共享,确保程序的稳定性和安全性。

    java多线程示例

    在Java编程语言中,多线程是核心特性之一,它允许程序同时执行多个任务,从而提高了应用程序的效率和响应...文档“java多线程实例.docx”可能包含具体的示例代码和详细解释,建议参考学习,以加深对Java多线程的理解。

    java多线程Demo

    Java多线程是Java编程中的一个重要概念,它允许程序同时执行多个任务,提高了程序的效率和响应速度。在Java中,实现多线程有两种主要方式:继承Thread类和实现Runnable接口。 1. 继承Thread类: 当我们创建一个新...

    java 多线程操作数据库

    ### Java多线程操作数据库:深入解析与应用 在当今高度并发的应用环境中,Java多线程技术被广泛应用于处理数据库操作,以提升系统的响应速度和处理能力。本文将基于一个具体的Java多线程操作数据库的应用程序,深入...

    易语言大漠多线程例子.rar

    线程函数是线程运行时执行的代码,创建线程对象则会分配必要的资源,启动线程使其开始执行。 在多线程编程中,需要注意线程间的通信和同步问题。易语言提供了信号量、事件、互斥量等机制来控制线程间的交互,确保...

    java 多线程并发实例

    在Java编程中,多线程并发是提升程序执行效率、充分利用多核处理器资源的重要手段。本文将基于"java 多线程并发实例"这个主题,深入探讨Java中的多线程并发概念及其应用。 首先,我们要了解Java中的线程。线程是...

    java 多线程 控制按钮移动 例子

    在【标题】"java 多线程 控制按钮移动 例子"中,提到的是使用多线程来实现GUI(图形用户界面)中的按钮动态移动,这通常涉及到事件处理和线程同步。 【描述】提到了多线程的概念,它允许并发执行多个指令流,每个...

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

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

    Java多线程矩阵相乘的代码

    这个压缩包中的内容,"Java多线程矩阵相乘的代码",显然提供了一个示例,演示如何利用多线程来加速矩阵乘法这一计算密集型操作。矩阵相乘在科学计算、图像处理、机器学习等领域广泛应用,其效率直接影响程序性能。 ...

    Java多线程编程

    9. **并发容器**:Java并发包提供了线程安全的容器,如`ConcurrentHashMap`、`CopyOnWriteArrayList`等,它们在多线程环境下保证了数据的一致性和正确性,减少了同步的开销。 10. **线程优先级**:Java中的线程有...

    Java 多线程 PPT

    本文将深入探讨Java多线程的相关概念、线程类和接口的使用,以及线程的同步与互斥。 首先,我们需要理解进程与线程的基本概念。程序是一组静态指令的集合,而进程则是程序在执行过程中的一个实例,拥有独立的内存...

    java+多线程+同步详解源代码学习

    Java多线程与同步是Java编程中的核心概念,它们在构建高效、响应迅速的应用程序时起着至关重要的作用。在大型系统开发中,多线程技术使得程序能够同时执行多个任务,提高系统的并发性,而同步机制则确保了在多线程...

    java多线程经典讲义

    Java多线程是Java编程中一个非常重要的领域,它允许程序在同一时间执行多个任务,从而提高了效率和资源利用率。在Java中,线程是进程中的一个执行单元,每个进程至少包含一个线程,通常Java虚拟机(JVM)启动时会...

    java 多线程示例

    Java提供了synchronized关键字来实现线程同步,确保同一时刻只有一个线程能执行特定代码块。 5. **死锁** 死锁是两个或多个线程相互等待对方释放资源而造成的僵局。避免死锁的关键在于遵循资源请求的顺序化和避免...

    Java多线程编程模板

    Java集合框架提供了线程安全的容器,如Vector、Collections.synchronizedList()、ConcurrentHashMap等,它们在多线程环境下自动进行同步。 总之,Java多线程编程是高效利用系统资源、提升程序性能的重要手段。理解...

    java多线程代码demo

    本示例代码集合("java多线程代码demo")涵盖了多线程的多种实现方式,包括Thread类和Runnable接口的使用,以及对死锁的理解与避免。通过以下详细解释,你可以深入了解Java多线程的原理和实践。 1. **Thread类**:...

    Java多线程端口快速扫描

    - `synchronized`关键字:在多线程环境下,可能需要确保某些代码块在同一时间只被一个线程执行,以防止数据竞争。在端口扫描程序中,可能会用到`synchronized`来保护共享资源,如扫描结果的存储。 - `wait()`, `...

Global site tag (gtag.js) - Google Analytics