java 并发

能够写出高伸缩性的并发是一门艺术

 

在JAVA SE5中新增了3个包

  • java.util.concurrent
  • java.util.concurrent.atomic
  • java.util.concurrent.locks

在java的内存模型中,类的实例字段、静态字段和构成数组的对象元素都会被多个线程所共享,局部变量与方法参数都是线程私有的,不会被共享。

 

每个线程都有自己的工作内存(高速缓冲区),共享主内存的数据。线程对变量的所有操作(读取、赋值等)都必须在工作内存中进行,不能直接读写主内存的变量。不同的线程也无法访问对方工作内存中的变量,线程间变量值的传递均需要通过主内存来完成。

 

volatile保证新值能能立即同步到主内存,以及每次使用前即从住内存刷新

禁止指令重排(机器及的优化操作)

 

线程是cpu调度的基本单位,java语言提供了在不同硬件和操作系统平台下对线程操作的统一处理。

实现线程主要有3中方式:使用内核线程实现、使用用户线程实现和使用用户线程加轻量级进程混合实现。

不同虚拟机不同实现

java使用线程调度方式是抢占式的

线程状态:

  • 新建:创建后尚未启动的线程处于这种状态
  • 运行:Runable包含了操作系统线程状态中的Running和Ready,也就是处于此状态的线程有可能正在执行,也有可能正在等待cpu为它分配执行时间
  • 无限期等待:不会分配cpu执行时间,他们等待被其他线程显示的唤醒,没有设置Timeout的Object.wait()和Thread.join()、LockSupport.park()
  • 限期等待:也不会分配cpu执行事件,不过无需等待被其他线程显示的唤醒,一定时间后自动唤醒,Thread.sleep()、设置了参数的Object.wait()和Thread.join()、LockSupport.parkNanos()、LockSupport.parkUntil()。
  • 阻塞:阻塞在等待获得一个排他锁
  • 结束:以终止的线程状态,线程已经结束执行。

要保证线程安全,并不一定要进行同步,两者没有因果关系,同步知识保证共享数据争用时的正确手段,

 

synchronized修饰方法,锁是当前对象。静态的方法锁的是Class对象 。获取锁操作的粒度是线程。

		// 恢复被中断的状态
		Thread.currentThread().interrupt();

 

java.util.concurrent

这个包下有并发容器、和线程池

减少锁竞争:

  •   缩小锁的范围(快进快出)
  •   减小锁的粒度(通过所分解技术:将一个锁分解为两个锁)
  •   锁分段
  •   避免热点域

并发容器:http://flyouwith.iteye.com/blog/2206550

同步工具类:http://flyouwith.iteye.com/blog/2206610  

线程池:http://flyouwith.iteye.com/blog/2206623

 

 Thread对象表示的线程和Runnable对象表示的线程所执行的任务之间是紧耦合的。这对于小型应用程序来说没问题,但对于大规模并发应用来说,合理的做法是将线程的创建与管理和程序的其他部分分离开。封装这些功能的对象就是执行器

 

  • 执行器接口定义了三种类型的执行器对象。
  • 线程池是最常见的一种执行器的实现。
  • Fork/Join是JDK 7中引入的并发框架。
java.util.concurrent中包括三个Executor接口: 

  • Executor,一个运行新任务的简单接口。
  • ExecutorService,扩展了Executor接口。添加了一些用来管理执行器生命周期和任务生命周期的方法。
  • ScheduledExecutorService,扩展了ExecutorService。支持Future和定期执行任务。
通常来说,指向Executor对象的变量应被声明为以上三种接口之一,而不是具体的实现类。 
 

 

 

 

 

java.util.concurrent.atomic

可以对boolean 、int、 long、引用(V value)进行原子操作。

采用CAS(compareAndSwap)比较 交换的策略。原子操作,当且紧当内存地址中的值符合旧的预期值时,处理器用新值更新旧值。

 

 

java.util.concurrent.locks

        一种简单的可重入锁它们有能力收回获得锁的尝试。如果当前锁对象不可用,或者锁请求超时(如果超时时间已指定),tryLock方法会收回获取锁的请求。如果在锁获取前,另一个线程发送了一个中断,lockInterruptibly方法也会收回获取锁的请求

 

public class RunMain {

	static class Test {

		private Lock lock = new ReentrantLock();

		/**
		 * 获得锁
		 */
		public boolean isLock(Test t) {
			boolean b1 = false;
			boolean b2 = false;
			try {
				b1 = lock.tryLock();
				b2 = t.lock.tryLock();
			} finally {
				if (!(b1 && b2)) {
					if (b1)
						lock.unlock();
					if (b2)
						t.lock.unlock();
				}

			}
			return b1 && b2;
		}

		public void method1(Test t) {
			if (isLock(t)) {
				try {
					t.method2();
				} finally {
					System.err.println("执行成功释放锁");
					t.lock.unlock();
					lock.unlock();
				}
			}else{
				System.out.println("没有获得锁");
			}
		}

		public void method2() {
			System.err.println("-------");
		}
	}

	static class ThreadRun implements Runnable {

		private Test test;
		private Test test2;

		public ThreadRun(Test test, Test test2) {
			this.test = test;
			this.test2 = test2;
		}

		Random random = new Random();
		
		@Override
		public void run() {
			while(true){
				try{
					Thread.sleep(random.nextInt(10));
				}catch(InterruptedException e){}
				test.method1(test2);
			}
		}
	}

	public static void main(String[] args) {
		Test test1 = new Test();
		Test test2 = new Test();
		Thread t1 = new Thread(new ThreadRun(test1, test2));
		Thread t2 = new Thread(new ThreadRun(test2, test1));
		t1.start();
		t2.start();
		
	}
}

 

 

 

 

 

 

 

你可能感兴趣的:(java 并发)