--------概述---------
需要多任务处理的原因是 计算机的运算速度和它的存储和通讯子系统速度的差距太大,大部分时间都花在了磁盘IO,网络通信和数据访问上。
使用一些手段把处理器的运算能力压榨出来, 否则就会造成很大的浪费。
高速缓存 内存和CPU之间有几个数量级的差距,所以引入了高速缓存,用以通讯。
这就导致了缓存一致性的问题。
主内存,工作内存和Java内存区域中的堆栈方法区并不是同一个层次。如果要勉强对应起来
内存 --> 主内存 --> Java堆中的对象实例
寄存器/高速缓存 --> 工作内存 --> 对应了jvm栈中部分区域,
------栈堆方法区---------
栈:可以分为JVM栈(执行字节码) 本地方法栈(执行Native方法)
JVM栈: 线程私有的, 生命周期与线程相同,存储局部/本地变量表(基本数据类型,对象引用)
堆: 所有对象实例 和 数组 常量池, 成员变量(包括基本数据类型int)
常量池
http://www.cnblogs.com/devinzhang/archive/2012/01/25/2329463.html
方法区:也称永久代,不会被回收, 存储类信息,常量,静态变量
运行时常量池: 是方法区的一部分,String 的intern方法可以将数据放入
String str1="wang";
String str2=(new String("wang")).intern();
System.out.println(str1==str2); //true
使用方式
Object obj = new Object();
Object obj 反映到栈的本地变量表中, 作为一个reference类型数据出现
new Object() 反映到堆中,形成一块内存空间
对中还包含了能查找到此对象类型数据(对象类型,父类,接口,方法等),存放在方法区中
----------线程池------------
如果访问服务器的客户端很多,那么服务器要不断的创建和销毁线程, 这样将严重影响服务器的性能,如果真的来一名学员,我们就安排一名新的 工作人员为之服务,这也是不可能的,那么公司岂不是要招很多工作人员.
应该是一名工作人员服务完一名学员,空闲下来后,一旦有新的学员要服务,
我们安排该工作人员,为之服务.
线程池的概念于此类似,首先创建一些线程,他们的集合称为线程池,
当服务器接收到一个客户请求后,就从线程池中取出一个空闲的线程为之服
务,服务完成后不关闭该线程,而是将该线程还回到线程池中.
在线程池的编程模式下,任务是交给整个线程池,而不是直接交给某个线
程,线程池拿到任务偶,他就在内部找有空闲的线程,再把任务交给内部某个
空闲的线程,这就是封装.记住,任务是交给整个线程池,但可以同时向一个线程池中提交多个任务.
Log-monitor 中不是开所有的线程去访问32个instance上的日志, 而是只开10个,然后等这些结束后,继续执行剩下的
---------AtomicInteger--------
i++ 不是线程安全的,如果多个线程从1加到100 结果会小于100 需要用到synchronized
在i已从内存中取到最新值, 但未与1进行运算, 此时其他线程已数次将运算结果赋值给i.
则当前线程结束时, 之前的数次运算结果都将被覆盖. (非原子性)
AtomicInteger 是线程安全的,
调用了volatile,volatile保证每次取a的值都不是从缓存中取的,而是从a真正对应的内存地址,但它不能保证原子性。(可见性 )
区别于synchronized这种悲观锁,导致其他所有需要锁线程挂起,等待持有锁的线程释放锁。
CAS (Compare And Swap) 是一种乐观锁的机制
CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。
private volatile int value;
public final int get() {
return value;
}
public final int incrementAndGet() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return next;
}
}
在这里采用了CAS操作,每次从内存中读取数据然后将此数据和+1后的结果进行CAS操作,如果成功就返回结果,否则重试直到成功为止。
而compareAndSet利用JNI来完成CPU指令的操作。
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
整体的过程就是这样子的,利用CPU的CAS指令,同时借助JNI来完成Java的非阻塞算法。其它原子操作都是利用类似的特性完成的。
-----------内存模型------------
http://www.myexception.cn/other/1017209.html
在java中,所有实例域、静态域和
数组元素存储在堆内存中,堆内存在线程之间共享(本文使用“共享变量”这个术语代指实例域,静态域和数组元素)。局部变量(Local variables),方法定义参数(java语言规范称之为formal method parameters)和异常处理器参数(exception handler parameters)不会在线程之间共享,它们不会有内存可见性问题,也不受内存模型的影响。
线程A与线程B之间如要通信的话,必须要经历下面2个步骤:
首先,线程A把本地内存A中更新过的共享变量刷新到主内存中去。
然后,线程B到主内存中去读取线程A之前已更新过的共享变量。
如上图所示,本地内存A和B有主内存中共享变量x的副本。假设初始时,这三个内存中的x值都为0。线程A在执行时,把更新后的x值(假设值为1)临时存放在自己的本地内存A中。当线程A和线程B需要通信时,线程A首先会把自己本地内存中修改后的x值刷新到主内存中,此时主内存中的x值变为了1。随后,线程B到主内存中去读取线程A更新后的x值,此时线程B的本地内存的x值也变为了1。
java内存模型JMM主要是为了规定线程和内存之间的一些关系.
系统存在一个主内存, java中所有实例变量都存储在主内存中,对于所有线程是共享的
.每条线程都有自己的工作内存, 工作内存由缓存和堆栈两部分组成, 缓存中保存的是主存中变量的拷贝,
缓存不总和主存同步,也就是缓存中变量的修改可能没有立刻写到
主存中,堆栈中保存的是线程的局部变量,线程之间无法相互直接访问堆栈中的变量.
线程的working memory工作内存是
cpu的寄存器和高速缓存的抽象描述:现在的计算机,cpu在计算的时候,并不总是从内存读取数据,它的数据读取顺序优先级 是:寄存器-高速缓存-内存。线程耗费的是CPU,线程计算的时候,原始的数据来自内存,在计算过程中,有些数据可能被频繁读取,这些数据被存储在寄存器和高速缓存中,当线程计算完后,这些缓存的数据在适当的时候应该写回内存。当多个线程同时读写某个内存数据时,就会产生多线程并发问题,
原子性,有序性,可见性
原子性,对除了long和double之外的基本类型的简单操作都具有原子性。简单操作就是赋值或者return。比如”a = 1;”和 “return a;”这样的操作都具有原子性。但是在Java中,类似”a += b”这样的操作不具有原子性。
对long和double的简单操作不具有原子性。但是,一旦给这两个类型的属性加上volatile修饰符,对它们的简单操作就会具有原子性。
synchronized既保证了多线程的并发有序性,又保证了多线程的内存可见性。
volatile可以保证内存可见性,不能保证并发有序性。
AtomicInteger 中用volatile解决可见性问题, 用CAS来解决有序性问题
--------ThreadLocal---------
当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。 不存在变量共享的问题
-------线程安全的实现方法--------
1> 互斥同步 synchronized Lock(不推荐)
2> 非阻塞同步 CAS Compare And Swap
AtomicInteger
3> 无同步方案 不涉及共享数据, 一般的web应用
临时变量, ThreadLocal
总结 用同步的方式来解决多线程问题,是由于用到了共享变量,如果没有共享变量则无需用同步。
---------共享数据类型------------
1> 不可变 final修饰的基本数据类型
2> 绝对线程安全 定义: 调用者不需要任何额外的同步措施
没有绝对安全的,多线程频繁的对Vector进行add get remove 操作,也会出现数组越界异常。
需要用到同步块synchronized(vector){....}
3> 相对线程安全
Vector HashTable
4> 线程兼容 (线程不安全)
ArrayList HashMap
package com.hp.hpsc.logservice.client;
import java.util.Vector;
public class TestVector {
private static Vector<Integer> vector = new Vector<Integer>();
public static void main(String[] args) {
while(true){
for (int i = 0; i < 10; i++) {
vector.add(i);
}
Thread removeThread = new Thread(new Runnable(){
@Override
public void run() {
for (int i = 0; i < vector.size(); i++) {
vector.remove(i);
}
}
});
Thread printThread = new Thread(new Runnable(){
@Override
public void run() {
for (int i = 0; i < vector.size(); i++) {
System.out.println(Thread.currentThread().getName() +":" + vector.get(i));
}
}
});
removeThread.start();
printThread.start();
while (Thread.activeCount() > 20);
}
}
}
异常
Exception in thread "Thread-1293" java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 12
at java.util.Vector.get(Vector.java:694)
at com.hp.hpsc.logservice.client.TestVector$2.run(TestVector.java:28)
at java.lang.Thread.run(Thread.java:619)
分享到:
相关推荐
### C++09内存模型与多线程编程 #### 一、引言 随着多核处理器的普及,多线程编程成为了现代软件开发中的一个重要组成部分。C++作为一门广泛使用的编程语言,在C++09标准中引入了一系列重要的新特性,其中最显著的...
本文将深入探讨如何在rt-thread操作系统环境下实现一个高效的多线程TCP并发服务器模型。 rt-thread是一个开源、实时、轻量级的操作系统,特别适合于嵌入式设备。它提供了丰富的API接口,支持网络协议栈,使得开发者...
Java内存模型,简称JMM(Java Memory Model),是Java虚拟机规范中定义的一个抽象概念,它描述了在多线程环境下,如何保证各个线程对共享数据的一致性视图。JMM的主要目标是定义程序中各个变量的访问规则,以及在...
Java内存模型(JVM Memory Model,简称JMM)是Java平台中的一个重要概念,它定义了在多线程环境下,如何在共享内存中读写变量的行为。JMM的主要目标是确保多线程环境下的可见性、有序性和原子性,从而避免数据不一致...
在实际应用中,"php-多线程扩展"可以与PHP的其他组件如PDO(数据库访问)、cURL(HTTP客户端)或者Redis(内存数据存储)结合使用,以多线程方式并行处理数据库查询、网络请求或者缓存操作,大大提高系统的并发处理...
此外,线程间通信(如wait/notify、生产者消费者模型)也是多线程编程中的重要概念。 高并发是指系统在同一时间能处理大量并发请求的能力。在互联网服务中,高并发处理能力直接影响到系统的可扩展性和性能。为了...
Java内存模型(JVM Memory Model)是Java编程语言中用于定义如何在多线程环境下共享变量的规则。在这个模型中,内存屏障(Memory Barrier)和重排序(Reordering)是两个关键概念,它们对并发编程的正确性和性能有着...
此外,Java内存模型(JMM)也是多线程编程中的重要概念,它定义了线程如何共享和访问内存,以及如何确保内存可见性。volatile关键字可以确保变量对所有线程可见,而final关键字则保证初始化的值不会被其他线程改变。...
4. **非阻塞I/O**:结合异步I/O或事件驱动模型(如Epoll、Kqueue),可以进一步提高多线程Twemproxy的效率,使其在等待网络I/O时能处理其他请求,而不是简单地阻塞。 5. **性能监控**:为了确保多线程版本的稳定性...
在Java编程语言中,内存模型(Java Memory Model, JMM)是理解和解决多线程并发问题的关键。本文将深入探讨JMM中的三个核心概念:原子性、有序性和可见性。 ### 1. 原子性(Atomicity) 原子性是指一个操作或多个...
Java内存模型(JVM Memory Model,简称JMM)是Java平台中的一个重要概念,它定义了程序中各个变量的访问规则,以及在多线程环境下的内存一致性效果。JMM主要解决的是并发环境下不同线程之间如何共享数据以及如何保证...
本资料集专注于"Linux编程技术-多线程-网络编程",它涵盖了UNIX环境高级编程、Linux网络编程、Linux多线程编程、Linux窗口编程以及Linux脚本编程等多个核心主题。这些内容都是构建高效、可靠且可扩展的Linux应用的...
本篇文章将深入探讨Java内存模型(JMM, Java Memory Model),以及其中的内存操作规则。 Java内存模型定义了在并发环境中,如何在不同线程之间共享数据以及保证数据一致性的一组规范。它主要关注的是处理器内存和...
### 并发编程基础知识,Java内存模型及多线程、volatile #### Java内存模型(JMM) Java内存模型(Java Memory Model, JMM)是Java并发编程的基础之一,它定义了一套规则来保证线程之间的数据可见性和一致性。当程序...
当我们谈论“OC-多线程-上下文切换”时,我们实际上是在讨论Objective-C中多线程环境下的一个核心概念。上下文切换是操作系统调度线程执行的一种机制,它涉及到保存当前线程的状态并恢复另一个线程的状态,以便线程...
9. **Java内存模型(JMM)**: - 描述了线程如何访问和修改共享变量,确保并发场景下的正确性。 - 主要概念包括主内存、工作内存、happens-before原则等。 10. **线程安全**: - 线程安全是指在多线程环境下,对...
在本项目实践中,我们主要探讨的是如何利用多线程和多进程技术来提高下载效率,特别是在人工智能相关的场景中。多线程和多进程是计算机科学中的核心概念,它们允许程序同时执行多个任务,从而实现并发处理,提升系统...
在本MFC教程Lesson 15中,我们将深入探讨多线程编程以及如何利用MFC(Microsoft Foundation Classes)框架创建一个简单的聊天室应用。多线程是现代软件开发中的一个重要概念,它允许程序同时执行多个任务,提高了...