多线程同步(Lock)

实例

模仿生产者和消费者的模式

先来个两个线程的

class ProducerConsumerDemo
{
	public static void main(String[] args)
	{
		Res r=new Res();
		Pro in=new Pro(r);
		Cou out=new Cou(r);
		Thread t1=new Thread(in);
		Thread t2=new Thread(out);
		t1.start();
		t2.start();
	}
}
class Res
{
	private String name;
	private int count=1;
	private boolean flag=false;
	public synchronized void set(String name)
	{
		if(flag)
			try{wait();}catch(Exception e){}
		this.name=name+"---"+count++;
			System.out.println(Thread.currentThread().getName()+"+++生产者+++"+this.name);
		flag=true;
		this.notify();
	}
	public synchronized void out()
	{
		if(!flag)
			try{wait();}catch(Exception e){}
			System.out.println(Thread.currentThread().getName()+"消费者"+this.name);
		flag=false;
		this.notify();
	}
}
class Pro implements Runnable
{
	private Res r;
	Pro(Res r)
	{
		this.r=r;
	}
	public void run()
	{
		while(true)
		{
			r.set("--商品--");
		}
	}
}
class Cou implements Runnable
{
	private Res r;
	Cou(Res r)
	{
		this.r=r;
	}
	public void run()
	{
		while(true)
		{
			r.out();
		}
	}
}

这样就OK了

下面就试试四个线程的,两个线程生产,两个线程消费;

class ProducerConsumerDemo
{
	public static void main(String[] args)
	{
		Res r=new Res();
		Pro in=new Pro(r);
		Cou out=new Cou(r);
		Thread t1=new Thread(in);
		Thread t2=new Thread(in);
		Thread t3=new Thread(out);
		Thread t4=new Thread(out);
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}
}
class Res
{
	private String name;
	private int count=1;
	private boolean flag=false;
	public synchronized void set(String name)
	{
		if(flag)
			try{wait();}catch(Exception e){}
		this.name=name+"---"+count++;
			System.out.println(Thread.currentThread().getName()+"+++生产者+++"+this.name);
		flag=true;
		this.notify();
	}
	public synchronized void out()
	{
		if(!flag)
			try{wait();}catch(Exception e){}
			System.out.println(Thread.currentThread().getName()+"消费者"+this.name);
		flag=false;
		this.notify();
	}
}
class Pro implements Runnable
{
	private Res r;
	Pro(Res r)
	{
		this.r=r;
	}
	public void run()
	{
		while(true)
		{
			r.set("--商品--");
		}
	}
}
class Cou implements Runnable
{
	private Res r;
	Cou(Res r)
	{
		this.r=r;
	}
	public void run()
	{
		while(true)
		{
			r.out();
		}
	}
}

但结果是多生产少消费,并不是我们想要的一生产一消费;

改良代码

class ProducerConsumerDemo
{
	public static void main(String[] args)
	{
		Res r=new Res();
		Pro in=new Pro(r);
		Cou out=new Cou(r);
		Thread t1=new Thread(in);
		Thread t2=new Thread(in);
		Thread t3=new Thread(out);
		Thread t4=new Thread(out);
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}
}
class Res
{
	private String name;
	private int count=1;
	private boolean flag=false;
	public synchronized void set(String name)
	{
		while(flag)
			try{wait();}catch(Exception e){}
		this.name=name+"---"+count++;
			System.out.println(Thread.currentThread().getName()+"+++生产者+++"+this.name);
		flag=true;
		this.notifyAll();
	}
	public synchronized void out()
	{
		while(!flag)
			try{wait();}catch(Exception e){}
			System.out.println(Thread.currentThread().getName()+"消费者"+this.name);
		flag=false;
		this.notifyAll();
	}
}
class Pro implements Runnable
{
	private Res r;
	Pro(Res r)
	{
		this.r=r;
	}
	public void run()
	{
		while(true)
		{
			r.set("--商品--");
		}
	}
}
class Cou implements Runnable
{
	private Res r;
	Cou(Res r)
	{
		this.r=r;
	}
	public void run()
	{
		while(true)
		{
			r.out();
		}
	}
}

对于多个生产者和消费者。

为什么要定义while判断标记。

原因:让被唤醒的线程在一次判断标记。

为什么定义notifyAll?

因为需要唤醒对方线程。

以为只用notify,容易出现只唤醒本方线程的情况,导致程序中的所有线程都等待。

JDK新版中提供了多线程升级解决方案。

将同步Syschronized替换成现实Lock操作;

将Object中的wait, notify notifyAll,替换了Condition对象。

该对象可以Lock锁 进行获取。

实现了本方只唤醒对方的操作;

import java.util.concurrent.locks.*;
class ProducerConsumerDemo2
{
	public static void main(String[] args)
	{
		Res r=new Res();
		Pro in=new Pro(r);
		Cou out=new Cou(r);
		Thread t1=new Thread(in);
		Thread t2=new Thread(in);
		Thread t3=new Thread(out);
		Thread t4=new Thread(out);
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}
}
class Res
{
	private String name;
	private int count=1;
	private boolean flag=false;

	private Lock  lock=new ReentrantLock();
	private Condition  condition_in=lock.newCondition();
	private Condition  condition_out=lock.newCondition();

	public void set(String name)throws InterruptedException
	{
		lock.lock();
		try
		{
			while(flag)
				condition_in.await();
			this.name=name+"---"+count++;
				System.out.println(Thread.currentThread().getName()+"+++生产者+++"+this.name);
			flag=true;
			condition_out.signal();
		}
		finally
		{
			lock.unlock();//解锁对象一定要执行
		}
	}
	public void out()throws InterruptedException
	{
		lock.lock();
		try
		{
			while(!flag)
				condition_out.await();
				System.out.println(Thread.currentThread().getName()+"消费者"+this.name);
			flag=false;
			condition_in.signal();
		}
		finally
		{
			lock.unlock();
		}

	}
}
class Pro implements Runnable
{
	private Res r;
	Pro(Res r)
	{
		this.r=r;
	}
	public void run()
	{
		try
		{
			while(true)
			{
				r.set("--商品--");
			}
		}
		catch (InterruptedException e)
		{
		}

	}
}
class Cou implements Runnable
{
	private Res r;
	Cou(Res r)
	{
		this.r=r;
	}
	public void run()
	{
		try
		{
			while(true)
			{
				r.out();
			}
		}
		catch (InterruptedException e)
		{
		}
	}
}

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

时间: 2024-10-26 20:05:54

多线程同步(Lock)的相关文章

通过Lock对象以及Condition对象实现多线程同步

通过Lock对象以及Condition对象实现多线程同步: 在之前的学习中,无论是通过synchronized建立同步代码块,还是通过synchronized建立同步函数,都是把对象看成一把锁来实现同步,这种解释有点牵强,而且在消费者-生产者的那个实例中,其实还有个问题,那就是在避免线程全部冻结时,没必要把相同功能的线程解冻,只要把其他功能的线程解冻即可,也就是说消费者线程只要解冻生产者线程即可,没必要把其他消费者线程也解冻,为了解决这些问题,java1.5版本推出了同步的升级办法,那就是通过L

读写锁(read-write lock)机制-----多线程同步问题的解决

读写锁(read-write lock)一 综述    在一些程序中存在读者写者问题,也就是说,对某些资源的访问会  存在两种可能的情况,一种是访问必须是排它行的,就是独占的意思,这称作写操作:另一种情况就是访问方式可以是共享的,就是说可以有多个线程同时去访问某个资源,这种就称作读操作.这个问题模型是从对文件的读写操作中引申出来的.    读写锁比起mutex具有更高的适用性,具有更高的并行性,可以有多个线程同时占用读模式的读写锁,但是只能有一个线程占用写模式的读写锁,读写锁的三种状态:1.当读

多线程同步条件变量(转载)

最近看<UNIX环境高级编程>多线程同步,看到他举例说条件变量pthread_cond_t怎么用,愣是没有看懂,只好在网上找了份代码,跑了跑,才弄明白 [cpp] view plaincopy #include <pthread.h> #include <stdio.h> #include <stdlib.h> pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*初始化互斥锁*/ pthread_cond_

【python标准库学习】thread,threading(二)多线程同步

继上一篇介绍了python的多线程和基本用法.也说到了python中多线程中的同步锁,这篇就来看看python中的多线程同步问题. 有时候很多个线程同时对一个资源进行修改,这个时候就容易发生错误,看看这个最简单的程序: import thread, time count = 0 def addCount(): global count for i in range(100000): count += 1 for i in range(10): thread.start_new_thread(ad

Java多线程同步的方法

一 synchronized关键字 1.synchronized实现原理: ---基于对象监视器(锁) java中所有对象都自动含有单一的锁,JVM负责跟踪对象被加锁的次数.如果一个对象被解锁,其计数变为0.在任务(线程)第一次给对象加锁的时候, 计数变为1.每当这个相同的任务(线程)在此对象上获得锁时,计数会递增.只有首先获得锁的任务(线程)才能继续获取该对象上的多个锁.每当任务离开时,计数递减,当计数为0的时候,锁被完全释放. Java中每个对象或者类都有一把锁与之相关联,对于对象来说,监视

转:关于JAVA多线程同步

转:http://lanvis.blog.163.com/blog/static/26982162009798422547/ 因为需要,最近关注了一下JAVA多线程同步问题.JAVA多线程同步主要依赖于若干方法和关键字.将心得记录如下: 1  wait方法:        该方法属于Object的方法,wait方法的作用是使得当前调用wait方法所在部分(代码块)的线程停止执行,并释放当前获得的调用wait所在的代码块的锁,并在其他线程调用notify或者notifyAll方法时恢复到竞争锁状态

多线程同步精要

单机并发编程有两种基本模型:"消息传递"和"共享内存":分布式系统运行在多台机器上,只有一种实用模型:"消息传递". 单机上多进程并发可以照搬"消息传递",多线程编程用"消息传递"更容易保证程序的正确性. 多线程同步有很多种方式:互斥量.条件变量.信号量.读写锁等.尽量不要用信号量和读写锁 Don't use a semaphore where a mutex would suffice. A semaph

多线程同步_Monitor

多线程一直在学习和理解中...... Monitor类是多线程中用以实现同步的一种技术,主要是同一进程内多线程间的同步技术. Monitor类中有以下几个方法需要注意: Monitor.Enter(object obj)方法,其意义相当于Lock(obj): Monitor.Exit(object obj)方法,意思是释放被锁的对象 Monitor.Wait(object obj)方法,释放被锁的对象,并阻塞当前线程,等待其他线程通知(Pulse)再次获得锁 (个人理解 当前线程释放锁 自己也阻

Qt 多线程同步 与 通信

转自网络 1 多线程同步 Qt提供了以下几个类来完成这一点:QMutex.QMutexLocker.QSemphore.QWaitCondition. 当然可能还包含QReadWriteLocker.QReadLocker.QWriteLocker,但线程同步是应用很少,这里只做简单的讲解! QMutex.QMutexLocker QMutex类提供了一个保护一段临界区代码的方法,他每次只允许一个线程访问这段临界区代码.QMutex::lock()函数用来锁住互斥量,如果互斥量处于解锁状态,当前

Java中利用synchronized关键字实现多线程同步问题

Java 中多线程的同步依靠的是对象锁机制,synchronized关键字就是利用了封装对象锁来实现对共享资源的互斥访问. 下面以一个简单例子来说明多线程同步问题,我们希望在run()方法里加入synchronized关键字来实现互斥访问. package com.clark.thread; public class MyThread implements Runnable{     private int threadId;          public MyThread(int id){