soa---java 多线程的---锁

如今soa 与分布式计算已经成为互联网公司技术的标配

那他包括的知识点应该熟悉了解。并以此为基础,去应用,调优各种soa的框架。

包括例如以下的四点。是分布式的基础。

        a java 多线程 承接高吞吐量。

        b java nio 承接高并发,与交互协议的定制。

        c java 反射  完毕序列化与反序列化。

        d 设计模式的应用 保证应用的扩展性。

接上篇

由于说锁的原理比較的枯燥,得带着问题场景去说。才干看下去。才干研究下去。

在Java中Lock接口比synchronized块的优势是什么?你须要实现一个高效的缓存。它同意多个用户读,但仅仅同意一个用户写,以此来保持它的完整性,你会如何去实现它?

  这里主要是要考察说lock与synchronized 的差别。

1 利用cpu底层机制lock有读锁 与 写锁的区分。

2 在于上下文的切换与锁的竞争的优化。

3 关于死锁的避免

Synchronized  仅仅是jvm里面自己的一个协议;

而关于这个Lock 他的底层里面是有硬件支持的原子操作,各种cpu都支持的,各种平台也支持。假设须要具体理解。能够看看里面的源代码,里面有一个重要的类就是AbstractQueuedSynchronizer,  它是轮询处理。

synchronized 在取不到锁的时候。会休眠一段时间。这样要说开销非常大。

当然这样的synchronized 内部是后面的版本号能够进行优化的。

1 利用cpu底层机制lock有读锁 与 写锁的区分。

那实现上面题干的两种方式例如以下

synchronized样例

代码例如以下

public class SynchronizedMap<K,V> {
 private final Map<K,V> map=new HashMap<K, V>();

   public synchronized void put(K k,V v){
    map.put(k, v);
   }

   public synchronized V get(K k){
    return map.get(k);
   }

这样的排斥了 写/写,读/写 读/读。

对于lock,相关代码例如以下。

public class LockMap<K, V> {
 private final Map<K, V> map=new HashMap<K, V>();
 private final ReadWriteLock lock=new ReentrantReadWriteLock();
 private final Lock r=lock.readLock();
 private final Lock w=lock.writeLock();

 public void put(K key,V value){
  w.lock();
  try {
   map.put(key, value);
  } catch (Exception e) {
   e.printStackTrace();
  }finally{
   w.unlock();
  }

 }

 public V get(K key){
  r.lock();
  try {
   return map.get(key);
  } catch (Exception e) {
   e.printStackTrace();
  }finally{
   r.unlock();
  }
  return null;
 }

}

这样的排斥了 写/写 读/写 。

但读/读没有排斥。

也是就说读与读是多个线程能够同一时候读的。----能够做为读多写少的应用。

2在于上下文的切换与锁的竞争的优化。

对于 synchronized 来说。

他仅仅有一个条件队列的。里面放着相应于不同类型的(也能够说是处理不同业务类型的)线程。那这时。你仅仅能notifyall

。为了保证程序的正确,把全部的线程都叫起来,无论是不是你想要的业务类型的线程。这样的对于性能影响是很大的。比方10个线程在一个条件队列上等待,那么调用notifyAll 将唤醒全部的线程

这个时候线程产生例如以下:

a 它们会在锁上面产生竞争。

b 它们竞争完了之后大部分又大部分wait了

这两步。会导致了大量的线程上下文切换。

以及大量锁的竞争。

但这个lock是没问题的。他能够对于 不同的条件创建wait-set ,比方生产者消费者模式。生产者生产一个对象。这时想唤醒消费者。仅仅须要在对应的条件上面的wait set进行single.

对于线程安全的lock队列,与线程安全的synchronized stack代码

synchronized 代码例如以下

public class ProductStack {

	private Product[] products=new Product[10];
	private int index;

	public synchronized void addProduct(Product product){
		try {
			while(index>=(products.length-1)){//须要又一次检查一下。条件推断s
				System.out.println(" the product array is full ; "+Thread.currentThread().getName()+" is waiting");
				wait();
			}

				products[index]=product;
				index++;
				notifyAll();//为了能启动消费线程 当然也唤醒了生产线程。
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public synchronized Product pop(){
		Product product=null;
		try {

			while(index<=0){ //须要又一次检查一下。条件推断
				System.out.println("the product array is empty ;"+Thread.currentThread().getName() +"is waiting");
				wait();
			}
			    index--;
			    product=products[index];
				notifyAll();   //为了能启动 加入线程。 当然也唤醒了消费线程。
		} catch (Exception e) {
			e.printStackTrace();
		}

		return product;
	}
}

对于lock

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ProductQueue<V> {
	private final static int defaultSize=10;
	private final V[] queue;
	private int total;
	private int tail;
	private int head;
	private Lock lock=new ReentrantLock();
	private Condition notEmpty=lock.newCondition();
	private Condition notFull= lock.newCondition();

	public ProductQueue(){

		this(defaultSize);
	}

	public ProductQueue(int initialCapacity) {
		super();
		this.queue = (V[])new Object[initialCapacity];
	}

	public void push(V v) throws InterruptedException{
		lock.lock();
		try {
			while (isFull()) {
				notFull.await();
			}

			queue[tail] = v;
			++tail;
			if (tail == queue.length)
				tail = 0;
			total++;
			notEmpty.signal();//唤醒的是同一种类型的线程,不会浪费。

		} finally{
			lock.unlock();
		}

	}

	public V pop() throws InterruptedException{
		lock.lock();
		try {
			while(isEmpty()){
				notEmpty.await();
			}
			V v=queue[head];
			head++;
			if(head==queue.length)head=0;
			total--;
			notFull.signal();//唤醒的是同一种类型的线程,不会浪费。
			return v;
		} finally{
			lock.unlock();
		}
	}

	public boolean isEmpty(){
		return total==0;
	}
	public boolean isFull(){
		return total==queue.length;
	}

}

注解里面解释到了问题的根本。

notifyall 时将全部的线程,生产者,消费者都唤醒了。而此时你仅仅想唤醒生产者,或者仅仅想唤醒消费者,让你胡子眉毛一把抓

3 关于死锁的避免

产生死锁的本质:至少有两把以上的锁,每一个线程获取锁的方式不会一样。实际应用中会有例如以下3种情况,出现死锁

a  同一类对象

第一个方法

synchronized(LockA){

synchronized(LockB){

}

}

第二个方法

synchronized(LockB){

synchronized(LockA){

doSomeThing.......

}

}

以上情况的解决方式是。顺序不一样。把顺序搞一样就成。

b 对于方法 public void A(SameObject a,SameObject b){

synchronized(a){

synchronized(b){

doSomeThing.......

}

}

}

这里会产生死锁的可能,原因是依据參数的顺序就能有可能被锁了。 这时能够用并发包里面的tryLock最简单。         以上是在同一个类里面。

b  这样的情况,是在两个类里面。能够想象成为两个资源。

在类A里面的有一个a 方法是同步的。

在类B里面的有一个b 方法是同步的。

a 里面调b方法。

b 里面调a方法。

这里就会产生死锁,由于获取锁的顺序不一样。 这样的情况的解决方式是,将方法上的全部的synchronized的都去掉,换成同步块。但同步块同是将传过来的资源。进行一个copy. 这个在并发包里面的有些集合能够參考的。

全局,分析锁的个数。获取的顺序。顺序好说,那怎么分析?

怎么去分析死锁呢?

a 争取用同步块,把不能同步方法。从业务角度保证开方式调用。

b 用线程堆栈信息来分析(kill -3)的方式。

c 对于业务的拆解。

理论上没有死锁,可是锁管理的资源。在线程处理的时候,占时太长,将业务就要进行重构了。

d 加一功能代码 代码例如以下

ThreadMXBean tmx = ManagementFactory.getThreadMXBean();
  long[] ids = tmx.findDeadlockedThreads();
  if (ids != null) {
     ThreadInfo[] infos = tmx.getThreadInfo(ids, true, true);
     System.out.println("The following threads are deadlocked:");
     for (ThreadInfo ti : infos) {
        System.out.println(ti);
     }
    }
时间: 2024-10-17 05:24:32

soa---java 多线程的---锁的相关文章

Java 多线程与锁

多线程 线程和进程的区别 创建线程 通过实现Runnable 接口 1 class RunnableDemo implements Runnable{ 2 private Thread t; // create a thread 3 private String threadName; 4 5 RunnableDemo(String name){ 6 threadName = name; 7 System.out.println("Creating " + threadName); 8

【Java多线程】锁的优化策略

锁的优化策略 编码过程中可采取的锁优化的思路有以下几种: 1:减少锁持有时间 例如:对一个方法加锁,不如对方法中需要同步的几行代码加锁: 2:减小锁粒度 例如:ConcurrentHashMap采取对segment加锁而不是整个map加锁,提高并发性: 3:锁分离 根据同步操作的性质,把锁划分为的读锁和写锁,读锁之间不互斥,提高了并发性. 4:锁粗化 这看起来与思路1有冲突,其实不然.思路1是针对一个线程中只有个别地方需要同步,所以把锁加在同步的语句上而不是更大的范围,减少线程持有锁的时间: 而

java多线程编程——锁优化

并发环境下进行编程时,需要使用锁机制来同步多线程间的操作,保证共享资源的互斥访问.加锁会带来性能上的损坏,似乎是众所周知的事情.然而,加锁本身不会带来多少的性能消耗,性能主要是在线程的获取锁的过程.如果只有一个线程竞争锁,此时并不存在多线程竞争的情况,那么JVM会进行优化,那么这时加锁带来的性能消耗基本可以忽略.因此,规范加锁的操作,优化锁的使用方法,避免不必要的线程竞争,不仅可以提高程序性能,也能避免不规范加锁可能造成线程死锁问题,提高程序健壮性.下面阐述几种锁优化的思路. 一.尽量不要锁住方

java多线程(二)——锁机制synchronized(同步方法)

synchronized Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码.当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一个时间内只能有一个线程得到执行.另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块.然而,当一个线程访问object的一个加锁代码块时,另一个线程仍然可以访问该object中的非加锁代码块. ——以上来源百度百科 一.方法内的变量为线程安全 “非线程安全”的问题

Java多线程同步锁的理解

ava 多线程中同步锁的主要通过synchronized的关键字来实现的.让我们从一个买票程序说起吧. package com.day04; /** * * @author Administrator 问题描述:使用多线程的方式来模拟多个窗口买票 * */ public class SaleWindow implements Runnable { // 初始化票数10 private int ticket = 10; @Override public void run() { // 获取线程的名

java多线程(三)——锁机制synchronized(同步语句块)

用关键字synchronized声明方法在某些情况下是有弊端的,比如A线程调用同步方法之行一个长时间的任务,那么B线程必须等待比较长的时间,在这样的情况下可以使用synchronized同步语句快来解决. 一.用同步代码块解决同步方法的弊端 Task类 1 package com.weishiyao.learn.day4.testSynchorized.ep2; 2 3 public class Task { 4 5 private String getData1; 6 private Stri

Java多线程编程—锁优化

并发环境下进行编程时,需要使用锁机制来同步多线程间的操作,保证共享资源的互斥访问.加锁会带来性能上的损坏,似乎是众所周知的事情.然而,加锁本身不会带来多少的性能消耗,性能主要是在线程的获取锁的过程.如果只有一个线程竞争锁,此时并不存在多线程竞争的情况,那么JVM会进行优化,那么这时加锁带来的性能消耗基本可以忽略.因此,规范加锁的操作,优化锁的使用方法,避免不必要的线程竞争,不仅可以提高程序性能,也能避免不规范加锁可能造成线程死锁问题,提高程序健壮性.下面阐述几种锁优化的思路. 一.尽量不要锁住方

JAVA多线程---无锁

无锁是一种乐观策略,使用CAS(compare and swap)来鉴别线程冲突,如果发生冲突,就重试当前操作直到没有冲突为止. CAS(V,E,N) V要更新的变量,E表示预期值,N表示心值 仅当V=E时,才会将V设置为N  如果V!=E 说明已经有其他线程做了更新 当前线程什么也不做 CAS操作即使没有锁,也可以发现其他线程对当前线程的干扰,并进行恰当的处理. AtomicInteger #final boolean compareAndSet(int expect, int u)  //如

Java多线程的常见例子

一.相关知识: Java多线程程序设计到的知识: (一)对同一个数量进行操作 (二)对同一个对象进行操作 (三)回调方法使用 (四)线程同步,死锁问题 (五)线程通信 等等 二.示例一:三个售票窗口同时出售20张票; 程序分析:1.票数要使用同一个静态值 2.为保证不会出现卖出同一个票数,要java多线程同步锁. 设计思路:1.创建一个站台类Station,继承Thread,重写run方法,在run方法里面执行售票操作!售票要使用同步锁:即有一个站台卖这张票时,其他站台要等这张票卖完! 2.创建

java多线程(五)

Java 多线程同步 锁机制与synchronized 打个比方:一个object就像一个大房子,大门永远打开.房子里有很多房间(也就是方法).这些房间有上锁的(synchronized方法), 和不上锁之分(普通方法).房门口放着一把钥匙(key),这把钥匙可以打开所有上锁的房间.另外我把所有想调用该对象方法的线程比喻成想进入这房子某个 房间的人.所有的东西就这么多了,下面我们看看这些东西之间如何作用的. 在此我们先来明确一下我们的前提条件.该对象至少有一个synchronized方法,否则这