`
小路青青0113
  • 浏览: 22724 次
  • 性别: Icon_minigender_2
文章分类
社区版块
存档分类
最新评论
阅读更多
线程模型

一、同步模型

最常见的例子就是银行取款,A,B两个人分别在银行对一个账户进行取款操作,账户仅有1000余额,当同事点击取款1000的按钮时,银行会怎样处理呢?
每个人都查询到了余额1000元没错,即使同时取款,也会有一方不成功的,否则的话,银行会被搞垮的,他才没那么笨,但是这该如何实现呢?


1、synchronized同步关键字
这里涉及到多个线程对共享资源进行处理,这里就必须要给线程“排队”,使用的关键字是synchronized(同步),在程序中,给对共享资源进行处理的代码部分(整个方法或代码块)添加此关键字。相当于给代码块加锁,取得钥匙的线程对资源操作,完成后将钥匙交予其他线程,这保证了同一个资源某一时间内只有一个线程可以对其修改等操作。
public void func(){
    //代码
    synchronized(锁){
         //对共享资源处理代码
    }
    //代码
}
这里注意:
      (1)、锁本身必须是共享的资源,不能使局部变量,如在方法内部定义锁,然后使用的话,这样的代码是无意义的,每个对象都会实例化一个锁,锁就失去了作用。比如超市的储物柜钥匙如果每人一把的话,那谁还敢把东西放进去呢。
public void func(){
   Object lock = new Object();
    //代码
    synchronized(lock){//锁失去了意义
         //对共享资源处理代码
    }
    //代码
}
     (2)、锁可以是任何一个类型即Object
     (3)、注意细分锁。可以有多个锁对象,对不同的资源“上锁”
class A{
     private Object lock1 = new Object();
     private Object lock2 = new Object();
    
     void f(){
           synchronized(lock1){
                 //访问资源P
           }
     }

     void g(){
           synchronized(lock2){
                 //访问资源Q
           }
     }
}



2、Lock 锁对象
除了synchronized还可以用Lock创建临界区
class A{
     Lock lock = new ReentrantLock();
     void f(){
           
            lock.lock();//加锁
              try{
                  //访问资源            
            }finally{
                  lock.unlock();//解锁
             }
     }
]



3、synchronized 和 Lock
(1)Lock的锁定时通过代码实现的,synchronized是在JVM层面上实现的
(2)synchronized在锁定时如果出现方法块抛出异常,JVM会自动解锁,不会造成因为异常而死锁。
Lock在出现异常时只能在finally{}将锁释放。
(3)Lock能完成synchronized所实现的所有功能
(4)Lock有比synchronized更精确的线程语义和更好的性能。
(5)在资源竞争不是很激烈的情况下,synchronized的性能优于ReentrantLock,但是当资源竞争很激烈时,synchronized的性能会下降几十倍,而ReentrantLock的性能维持常态。



二、生产/消费模型
生产者生产一件产品放到仓库,消费者从仓库取走产品,生产者再生产一件...
有几种方式呢?
1、消费者不停的问“有货吗?有货吗?有货吗?”。这无疑是很浪费资源的方式
2、wait()/notify()
消费者处于wait(),生产者生产出产品则notify(),然后wait()消费者收到信息进行消费,然后notify生产者,并在此处于wait(),生产者再继续生产...
生产者类的代码;

/**
 * 生产者线程:无数据时再存,存入一个就发通知
 * @author Administrator
 *
 */
public class ProduceThread extends Thread{
	//用来标记放入对象的每一个独立ID号
	private static int count = 0;
	//与消费线程或共同存取的对象列表
	private List shareList;
	
	public ProduceThread(List shareList){
		this.shareList = shareList;
	}
	
	public void run(){
		System.out.println("生产线程已经启动 。。。"+shareList.size());
		while(true){
			try{
				Thread.sleep(2000);
				synchronized(shareList){
					while(shareList.size()>0){
						shareList.wait();//有货,等待
					}
					while(shareList.size()==0){//无货,生产
						Student st = new Student();
						count++;
						st.id = count;
						st.name = count+"aaa";
						System.out.println("--->生产线程放入对象:"+st.toString());
						shareList.add(st);
						shareList.notify();//通知
					}
				}
			}catch(Exception ef){
				ef.printStackTrace();
			}
		}
	}	
}

消费者类的代码:
/**
 * 取数据线程:当有数据时取,取完通知
 * @author Administrator
 *
 */
public class CustomerThread extends Thread{

	private List shareList;
	
	public CustomerThread(List shareList){
		this.shareList = shareList;
	}
	
	public void run(){
		System.out.println("消费线程已经启动。。。"+shareList.size());
		while(true){
			try{
				synchronized(shareList){
					while(shareList.size()==0){
						//如果没有,消费线程则等待
						shareList.wait();
					}
					while(shareList.size()>0){
						System.out.println("<---消费线程取出 "+shareList.remove(0).toString());
						//取了一个已经,立即发出通知
						shareList.notify();
					}
				}
			}catch(Exception ef){
				ef.printStackTrace();
			}
		}
	}
}

注意wait()和sleep()的区别是:
wait()释放锁等待,而sleep()是不释放锁的,即,它在休眠的时候仍然占用资源。



三、双缓冲模型
双缓冲模型有两个队列A,B,生产者将产品放到队列A中,消费者从队列B中拿产品,当B队列为空时,将A队列的产品存入B。当B不为空时,消费者只管取货,生产者只管生产,两者之间没有直接的联系,只有B为空时,将B队列同步起来,再将A同步起来,A中产品倒入B。
这样,就可以大大减少处理同步的次数。





如有不足,欢迎指正!



3
2
分享到:
评论
2 楼 stevenjohn 2013-01-17  
楼主,好文
1 楼 GLC 2013-01-17  
操作系统的正好还没考、这个让我好好复习了很多啊。

相关推荐

    Java线程模型缺陷

    Java 编程语言的线程模型可能是此语言中最薄弱的部分。它完全不适合实际复杂程序的要求,而且也完全不是面向对象的。本文建议对 Java 语言进行重大修改和补充,以解决这些问题。 Java 语言的线程模型是此语言的一个...

    2022年Java线程模型缺陷Java教程.docx

    2022年Java线程模型缺陷Java教程.docx

    Java同步线程模型分析与改进

    目前普遍采用急救包(Band-Aid)类库的方式解决Java 线程模型存在的同步问题,但类库中的代码很难或无法实 ...通过扩展语法方法解决了同步问题,以确保使用Java线程所开发的 程序的稳定、可靠和可优化。

    java线程-Java内存模型

    java线程-Java内存模型;java线程-Java内存模型;java线程-Java内存模型;java线程-Java内存模型;java线程-Java内存模型;java线程-Java内存模型java线程-Java内存模型

    JAVA多线程模型详解

    对java线程技术进行了总结,并使用图形形象地描述了线程的概念和使用,适合初学者。

    java多线程编程总结

    Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:线程的交互 Java线程:线程的调度-休眠 Java线程:线程的调度-优先级 Java线程:线程的调度-让步 Java线程:线程的...

    java多线程经典模型生产者消费者

    java多线程经典模型生产者消费者java多线程经典模型生产者消费者java多线程经典模型生产者消费者java多线程经典模型生产者消费者java多线程经典模型生产者消费者java多线程经典模型生产者消费者java多线程经典模型...

    Java多线程编程总结

    Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:线程的交互 Java线程:线程的调度-休眠 Java线程:线程的调度-优先级 Java线程:线程的调度-让步 Java线程...

    java实现多线程经典模型生产者消费

    java实现多线程经典模型生产者消费java实现多线程经典模型生产者消费java实现多线程经典模型生产者消费java实现多线程经典模型生产者消费java实现多线程经典模型生产者消费java实现多线程经典模型生产者消费java实现...

    java多线程笔记

    Java线程:线程栈模型与线程的变量 12 Java线程:线程的调度-休眠 13 Java线程:线程的调度-优先级 16 Java线程:线程的调度-让步 19 Java线程:线程的调度-合并 22 Java线程:线程的调度-终止线程 25 Java线程:...

    Java内存模型和线程安全

    Java内存模型和线程安全,多线程开发,高并发处理,内存模型分析

    Java 线程总结

    Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:线程的交互 Java线程:线程的调度-休眠 Java线程:线程的调度-优先级 Java线程:线程的调度-让步 Java线程:线程的...

    java内存模型(有助理解多线程)

    java内存模型,对初学者比较实用,理解后有助于多线程编程等

    java内存模型和线程安全

    java内存模型和线程安全,详细解析java的 堆栈模型和线程机制

    Java线程安全问题_动力节点Java学院整理

    其实java的多线程并发问题最终都会反映在java的内存模型上,所谓线程安全无非是要控制多个线程对某个资源的有序访问或修改。总结java的内存模型,要解决两个主要的问题:可见性和有序性。我们都知道计算机有高速缓存...

    java线程安全测试

    java 线程安全的几个测试小例子,充分的理解JMM中的线程内存模型

    Java 线程间通信,生产者与消费者模型

    使用wait()和notify()实现的生产者与消费者模型,可以了解如何使用wait()和notify()进行线程间通信。(上一次上传的代码有一个问题没有考虑到,这次修补了——CSDN没法撤销资源,只能再上传了)

Global site tag (gtag.js) - Google Analytics