JAVA 并发编程-传统线程互斥技术(Synchronized)(三)

java线程互斥是为了保证,同一时刻最多只有一个线程执行该段代码。那么它的出现又是为了解决什么问题呢?账户存取款,在同一时间段只能让一个人进行操作。

下面来看一个简单实例(多线程带来的问题):

public class TraditionalThreadSynchronized {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		new TraditionalThreadSynchronized().init();
	}

	private void init(){
		//此方法同时启动两个线程,去调用同一个方法的打印名字
		final Outputer outputer = new Outputer();
		new Thread(new Runnable(){
			@Override
			public void run() {
				while(true){
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					outputer.output("zhangxiaoxiang");
				}
			}
		}).start();

		new Thread(new Runnable(){
			@Override
			public void run() {
				while(true){
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					outputer.output3("lihuoming");
				}

			}
		}).start();

	}

	static class Outputer{

		public void output(String name){
			int len = name.length();
//			synchronized (Outputer.class)
//			{
				for(int i=0;i<len;i++){
					System.out.print(name.charAt(i));
				}
				System.out.println();
//			}
		}

	}
}

打印结果为:

解决以上问题:

添加synchronized的关键字,即解开注释即可。

打印结果:

总结:

当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。即当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

注意:要互斥,必须让锁子是同一把。以上的demo中,两个线程都用的是同一个new出来的output,所以output就是同一个对象。

详细内容请参看博客[原]02____线程的同步(Synchronized)

简答说明:

public class Test implements Runnable {

    public int cash = 100;

    public synchronized void m() {
        System.out.println("m查看账户,余额为"+cash);
        try {
             Thread.sleep(2000);
        } catch (InterruptedException e) {
             e.printStackTrace();
        }
        cash = cash - 100;
        System.out.println("cash1 = " + cash);
    }

    public synchronized void run() {
        System.out.println("run查看账户,余额为"+cash);
        cash += 1000;
        try {
            Thread.sleep(5000);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
        System.out.println("cash2 = " + cash);
    }

    public static void main(String[] args) {
        Test test = new Test();
        Thread thrad = new Thread(test);
        thrad.start();
        test.m();
    }
}

添加synchronized关键字后可以看出。只要m或者run进行对账户进行操作,不论中途多长时间,或者睡眠多长时间,线程都要执行完这个方法以后才会执行其他的方法。两个方法都必须加synchronized关键字,并且两者锁定同一对象(此处锁定的对象是test对象)。也就是说,只要有一个线程进入test对象的任意一个加了锁的方法,其他线程就不能访问这个对象里加了相同锁的方法了。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-12 23:23:01

JAVA 并发编程-传统线程互斥技术(Synchronized)(三)的相关文章

【java并发】传统线程互斥技术—synchronized

在多个线程同时操作相同资源的时候,就会遇到并发的问题,如银行转账啊.售票系统啊等.为了避免这些问题的出现,我们可以使用synchronized关键字来解决,下面针对synchronized常见的用法做一个总结.首先写一个存在并发问题的程序,如下: public class TraditionalThreadSynchronized { public static void main(String[] args) { //在静态方法中不能new内部类的实例对象 //private Outputer

JAVA并发编程3_线程同步之synchronized关键字

在上一篇博客里讲解了JAVA的线程的内存模型,见:JAVA并发编程2_线程安全&内存模型,接着上一篇提到的问题解决多线程共享资源的情况下的线程安全问题. 不安全线程分析 public class Test implements Runnable { private int i = 0; private int getNext() { return i++; } @Override public void run() { // synchronized while (true) { synchro

JAVA 并发编程-传统线程同步通信技术(四)

首先介绍几个概念: wait()方法 wait()方法使得当前线程必须要等待,等到另外一个线程调用notify()或者notifyAll()方法. 当前的线程必须拥有当前对象的monitor,也即lock,就是锁. 线程调用wait()方法,释放它对锁的拥有权,然后等待另外的线程来通知它(通知的方式是notify()或者notifyAll()方法),这样它才能重新获得锁的拥有权和恢复执行. 要确保调用wait()方法的时候拥有锁,即,wait()方法的调用必须放在synchronized方法或s

Java并发编程1——线程状态、synchronized

以下内容主要总结自<Java多线程编程核心技术>,不定时补充更新. 一.线程的状态 Java中,线程的状态有以下6类:NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED.各状态之间的关系可用下图表示: 二.常用方法介绍 1.thread.start()和thread.run()的区别 1 public static void main(String[] args) { 2 Thread t = new Thread(); 3 t

JAVA并发编程4_线程同步之volatile关键字

上一篇博客JAVA并发编程3_线程同步之synchronized关键字中讲解了JAVA中保证线程同步的关键字synchronized,其实JAVA里面还有个较弱的同步机制volatile.volatile关键字是JAVA中的轻量级的同步机制,用来将变量的更新操作同步到其他线程.从内存可见性的角度来说,写入volatile变量相当于退出同步代码块,读取volatile变量相当于进入同步代码块. 旧的内存模型:保证读写volatile都直接发生在main memory中. 在新的内存模型下(1.5)

19、Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition

Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者模型:当队列满时,生产者需要等待队列有空间才能继续往里面放入商品,而在等待的期间内,生产者必须释放对临界资源(即队列)的占用权.因为生产者如果不释放对临界资源的占用权,那么消费者就无法消费队列中的商品,就不会让队列有空间,那么生产者就会一直无限等待下去.因此,一般情况下,当队列满时,会让生产者交出对

Java并发编程:线程的同步

.title { text-align: center } .todo { font-family: monospace; color: red } .done { color: green } .tag { background-color: #eee; font-family: monospace; padding: 2px; font-size: 80%; font-weight: normal } .timestamp { color: #bebebe } .timestamp-kwd

Java 并发编程:线程间的协作(wait/notify/sleep/yield/join)

Java并发编程系列[未完]: Java 并发编程:核心理论 Java并发编程:Synchronized及其实现原理 Java并发编程:Synchronized底层优化(轻量级锁.偏向锁) Java 并发编程:线程间的协作(wait/notify/sleep/yield/join) 一.线程的状态 Java中线程中状态可分为五种:New(新建状态),Runnable(就绪状态),Running(运行状态),Blocked(阻塞状态),Dead(死亡状态). New:新建状态,当线程创建完成时为新

Java并发编程:线程的创建

.title { text-align: center } .todo { font-family: monospace; color: red } .done { color: green } .tag { background-color: #eee; font-family: monospace; padding: 2px; font-size: 80%; font-weight: normal } .timestamp { color: #bebebe } .timestamp-kwd