- 浏览: 2653210 次
- 来自: 杭州
文章分类
- 全部博客 (1188)
- webwork (4)
- 网摘 (18)
- java (103)
- hibernate (1)
- Linux (85)
- 职业发展 (1)
- activeMQ (2)
- netty (14)
- svn (1)
- webx3 (12)
- mysql (81)
- css (1)
- HTML (6)
- apache (3)
- 测试 (2)
- javascript (1)
- 储存 (1)
- jvm (5)
- code (13)
- 多线程 (12)
- Spring (18)
- webxs (2)
- python (119)
- duitang (0)
- mongo (3)
- nosql (4)
- tomcat (4)
- memcached (20)
- 算法 (28)
- django (28)
- shell (1)
- 工作总结 (5)
- solr (42)
- beansdb (6)
- nginx (3)
- 性能 (30)
- 数据推荐 (1)
- maven (8)
- tonado (1)
- uwsgi (5)
- hessian (4)
- ibatis (3)
- Security (2)
- HTPP (1)
- gevent (6)
- 读书笔记 (1)
- Maxent (2)
- mogo (0)
- thread (3)
- 架构 (5)
- NIO (5)
- 正则 (1)
- lucene (5)
- feed (4)
- redis (17)
- TCP (6)
- test (0)
- python,code (1)
- PIL (3)
- guava (2)
- jython (4)
- httpclient (2)
- cache (3)
- signal (1)
- dubbo (7)
- HTTP (4)
- json (3)
- java socket (1)
- io (2)
- socket (22)
- hash (2)
- Cassandra (1)
- 分布式文件系统 (5)
- Dynamo (2)
- gc (8)
- scp (1)
- rsync (1)
- mecached (0)
- mongoDB (29)
- Thrift (1)
- scribe (2)
- 服务化 (3)
- 问题 (83)
- mat (1)
- classloader (2)
- javaBean (1)
- 文档集合 (27)
- 消息队列 (3)
- nginx,文档集合 (1)
- dboss (12)
- libevent (1)
- 读书 (0)
- 数学 (3)
- 流程 (0)
- HBase (34)
- 自动化测试 (1)
- ubuntu (2)
- 并发 (1)
- sping (1)
- 图形 (1)
- freemarker (1)
- jdbc (3)
- dbcp (0)
- sharding (1)
- 性能测试 (1)
- 设计模式 (2)
- unicode (1)
- OceanBase (3)
- jmagick (1)
- gunicorn (1)
- url (1)
- form (1)
- 安全 (2)
- nlp (8)
- libmemcached (1)
- 规则引擎 (1)
- awk (2)
- 服务器 (1)
- snmpd (1)
- btrace (1)
- 代码 (1)
- cygwin (1)
- mahout (3)
- 电子书 (1)
- 机器学习 (5)
- 数据挖掘 (1)
- nltk (6)
- pool (1)
- log4j (2)
- 总结 (11)
- c++ (1)
- java源代码 (1)
- ocr (1)
- 基础算法 (3)
- SA (1)
- 笔记 (1)
- ml (4)
- zokeeper (0)
- jms (1)
- zookeeper (5)
- zkclient (1)
- hadoop (13)
- mq (2)
- git (9)
- 问题,io (1)
- storm (11)
- zk (1)
- 性能优化 (2)
- example (1)
- tmux (1)
- 环境 (2)
- kyro (1)
- 日志系统 (3)
- hdfs (2)
- python_socket (2)
- date (2)
- elasticsearch (1)
- jetty (1)
- 树 (1)
- 汽车 (1)
- mdrill (1)
- 车 (1)
- 日志 (1)
- web (1)
- 编译原理 (1)
- 信息检索 (1)
- 性能,linux (1)
- spam (1)
- 序列化 (1)
- fabric (2)
- guice (1)
- disruptor (1)
- executor (1)
- logback (2)
- 开源 (1)
- 设计 (1)
- 监控 (3)
- english (1)
- 问题记录 (1)
- Bitmap (1)
- 云计算 (1)
- 问题排查 (1)
- highchat (1)
- mac (3)
- docker (1)
- jdk (1)
- 表达式 (1)
- 网络 (1)
- 时间管理 (1)
- 时间序列 (1)
- OLAP (1)
- Big Table (0)
- sql (1)
- kafka (1)
- md5 (1)
- springboot (1)
- spring security (1)
- Spring Boot (3)
- mybatis (1)
- java8 (1)
- 分布式事务 (1)
- 限流 (1)
- Shadowsocks (0)
- 2018 (1)
- 服务治理 (1)
- 设计原则 (1)
- log (0)
- perftools (1)
最新评论
-
siphlina:
课程——基于Python数据分析与机器学习案例实战教程分享网盘 ...
Python机器学习库 -
san_yun:
leibnitz 写道hi,我想知道,无论在92还是94版本, ...
hbase的行锁与多版本并发控制(MVCC) -
leibnitz:
hi,我想知道,无论在92还是94版本,更新时(如Puts)都 ...
hbase的行锁与多版本并发控制(MVCC) -
107x:
不错,谢谢!
Latent Semantic Analysis(LSA/ LSI)算法简介 -
107x:
不错,谢谢!
Python机器学习库
在操作系统中,有两种不同的方法提供线程支持:用户层的用户线程,或内核层的内核线程。
其中用户线程在内核之上支持,并在用户层通过线程库来实现。不需要用户态/核心态切换,速度快。操作系统内核不知道多线程的存在,因此一个线程阻塞将使得整个进程(包括它的所有线程)阻塞。由于这里的处理器时间片分配是以进程为基本单位,所以每个线程执行的时间相对减少。
内核线程由操作系统直接支持。由操作系统内核创建、调度和管理。内核维护进程及线程的上下文信息以及线程切换。一个内核线程由于I/O操作而阻塞,不会影响其它线程的运行。
Java线程的实现是怎样的呢?我们通过SUN Java 6的源码了解其在Windows和Linux下的实现。
在Windows下的实现,os_win32.cpp中
bool os::create_thread(Thread * thread, ThreadType thr_type, size_t stack_size) {
unsigned thread_id;
// Allocate the OSThread object
OSThread * osthread = new OSThread(NULL, NULL);
if (osthread == NULL) {
return false ;
}
// Initial state is ALLOCATED but not INITIALIZED
{
MutexLockerEx ml(thread -> SR_lock(), Mutex::_no_safepoint_check_flag);
osthread -> set_state(ALLOCATED);
}
// Initialize support for Java interrupts
HANDLE interrupt_event = CreateEvent(NULL, true , false , NULL);
if (interrupt_event == NULL) {
delete osthread;
return NULL;
}
osthread -> set_interrupt_event(interrupt_event);
osthread -> set_interrupted( false );
thread -> set_osthread(osthread);
if (stack_size == 0 ) {
switch (thr_type) {
case os::java_thread:
// Java threads use ThreadStackSize which default value can be changed with the flag -Xss
if (JavaThread::stack_size_at_create() > 0 )
stack_size = JavaThread::stack_size_at_create();
break ;
case os::compiler_thread:
if (CompilerThreadStackSize > 0 ) {
stack_size = (size_t)(CompilerThreadStackSize * K);
break ;
} // else fall through:
// use VMThreadStackSize if CompilerThreadStackSize is not defined
case os::vm_thread:
case os::pgc_thread:
case os::cgc_thread:
case os::watcher_thread:
if (VMThreadStackSize > 0 ) stack_size = (size_t)(VMThreadStackSize * K);
break ;
}
}
// Create the Win32 thread
//
// Contrary to what MSDN document says, "stack_size" in _beginthreadex()
// does not specify stack size. Instead, it specifies the size of
// initially committed space. The stack size is determined by
// PE header in the executable. If the committed "stack_size" is larger
// than default value in the PE header, the stack is rounded up to the
// nearest multiple of 1MB. For example if the launcher has default
// stack size of 320k, specifying any size less than 320k does not
// affect the actual stack size at all, it only affects the initial
// commitment. On the other hand, specifying 'stack_size' larger than
// default value may cause significant increase in memory usage, because
// not only the stack space will be rounded up to MB, but also the
// entire space is committed upfront.
//
// Finally Windows XP added a new flag 'STACK_SIZE_PARAM_IS_A_RESERVATION'
// for CreateThread() that can treat 'stack_size' as stack size. However we
// are not supposed to call CreateThread() directly according to MSDN
// document because JVM uses C runtime library. The good news is that the
// flag appears to work with _beginthredex() as well.
#ifndef STACK_SIZE_PARAM_IS_A_RESERVATION
#define STACK_SIZE_PARAM_IS_A_RESERVATION (0x10000)
#endif
HANDLE thread_handle =
(HANDLE)_beginthreadex(NULL,
(unsigned)stack_size,
(unsigned (__stdcall * )( void * )) java_start,
thread,
CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION,
& thread_id);
if (thread_handle == NULL) {
// perhaps STACK_SIZE_PARAM_IS_A_RESERVATION is not supported, try again
// without the flag.
thread_handle =
(HANDLE)_beginthreadex(NULL,
(unsigned)stack_size,
(unsigned (__stdcall * )( void * )) java_start,
thread,
CREATE_SUSPENDED,
& thread_id);
}
if (thread_handle == NULL) {
// Need to clean up stuff we've allocated so far
CloseHandle(osthread -> interrupt_event());
thread -> set_osthread(NULL);
delete osthread;
return NULL;
}
Atomic::inc_ptr((intptr_t * ) & os::win32::_os_thread_count);
// Store info on the Win32 thread into the OSThread
osthread -> set_thread_handle(thread_handle);
osthread -> set_thread_id(thread_id);
// Initial thread state is INITIALIZED, not SUSPENDED
{
MutexLockerEx ml(thread -> SR_lock(), Mutex::_no_safepoint_check_flag);
osthread -> set_state(INITIALIZED);
}
// The thread is returned suspended (in state INITIALIZED), and is started higher up in the call chain
return true ;
}
可以看出,SUN JVM在Windows下的实现,使用_beginthreadex来创建线程,注释中也说明了为什么不用“Window编程书籍推荐使用”的CreateThread函数。由此看出,Java线程在Window下的实现是使用内核线程。
摘自<<windows操作系统原理>>
内核线程:由操作系统内核创建和撤销,内核维护进程及线程的上下文信息以及线程的切换,一个内核线程由于I/O操作而阻塞,
不会影响其他线程的运行,windows NT和2000 支持内核线程。
用户线程:由应用进程利用线程库创建和管理,不依赖操作系统的核心,不需要用户态/内核态的切换,速度快,操作系统内核不知道
多线程的存在,因此一个线程阻塞将使得整个进程(包括它的所有的线程)阻塞,由于这里的处理器时间片分配是以进程为基本单位的。所以每个线程执行的时间相对减少。
而在Linux下又是怎样的呢?
在os_linux.cpp文件中的代码摘录如下:
bool os::create_thread(Thread * thread, ThreadType thr_type, size_t stack_size) {
assert(thread -> osthread() == NULL, " caller responsible " );
// Allocate the OSThread object
OSThread * osthread = new OSThread(NULL, NULL);
if (osthread == NULL) {
return false ;
}
// set the correct thread state
osthread -> set_thread_type(thr_type);
// Initial state is ALLOCATED but not INITIALIZED
osthread -> set_state(ALLOCATED);
thread -> set_osthread(osthread);
// init thread attributes
pthread_attr_t attr;
pthread_attr_init( & attr);
pthread_attr_setdetachstate( & attr, PTHREAD_CREATE_DETACHED);
// stack size
if (os::Linux::supports_variable_stack_size()) {
// calculate stack size if it's not specified by caller
if (stack_size == 0 ) {
stack_size = os::Linux::default_stack_size(thr_type);
switch (thr_type) {
case os::java_thread:
// Java threads use ThreadStackSize which default value can be changed with the flag -Xss
if (JavaThread::stack_size_at_create() > 0 ) stack_size = JavaThread::stack_size_at_create();
break ;
case os::compiler_thread:
if (CompilerThreadStackSize > 0 ) {
stack_size = (size_t)(CompilerThreadStackSize * K);
break ;
} // else fall through:
// use VMThreadStackSize if CompilerThreadStackSize is not defined
case os::vm_thread:
case os::pgc_thread:
case os::cgc_thread:
case os::watcher_thread:
if (VMThreadStackSize > 0 ) stack_size = (size_t)(VMThreadStackSize * K);
break ;
}
}
stack_size = MAX2(stack_size, os::Linux::min_stack_allowed);
pthread_attr_setstacksize( & attr, stack_size);
} else {
// let pthread_create() pick the default value.
}
// glibc guard page
pthread_attr_setguardsize( & attr, os::Linux::default_guard_size(thr_type));
ThreadState state;
{
// Serialize thread creation if we are running with fixed stack LinuxThreads
bool lock = os::Linux::is_LinuxThreads() && ! os::Linux::is_floating_stack();
if ( lock ) {
os::Linux::createThread_lock() -> lock_without_safepoint_check();
}
pthread_t tid;
int ret = pthread_create( & tid, & attr, ( void * ( * )( void * )) java_start, thread);
pthread_attr_destroy( & attr);
if (ret != 0 ) {
if (PrintMiscellaneous && (Verbose || WizardMode)) {
perror( " pthread_create() " );
}
// Need to clean up stuff we've allocated so far
thread -> set_osthread(NULL);
delete osthread;
if ( lock ) os::Linux::createThread_lock() -> unlock();
return false ;
}
// Store pthread info into the OSThread
osthread -> set_pthread_id(tid);
// Wait until child thread is either initialized or aborted
{
Monitor * sync_with_child = osthread -> startThread_lock();
MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag);
while ((state = osthread -> get_state()) == ALLOCATED) {
sync_with_child -> wait(Mutex::_no_safepoint_check_flag);
}
}
if ( lock ) {
os::Linux::createThread_lock() -> unlock();
}
}
// Aborted due to thread limit being reached
if (state == ZOMBIE) {
thread -> set_osthread(NULL);
delete osthread;
return false ;
}
// The thread is returned suspended (in state INITIALIZED),
// and is started higher up in the call chain
assert(state == INITIALIZED, " race condition " );
return true ;
}
Java在Linux下的线程的创建,使用了pthread线程库,而pthread就是一个用户线程库,因此结论是,Java在
Linux下是使用用户线程实现的。Linux 2.6内核的pthread实现为NPTL,和内核线程的映射是一对一。之前的Linux
threads也是。
对于NPTL的一些介绍:
POSIX Thread Library (NPTL)使Linux内核可以非常有效的运行使用POSIX线程标准写的程序。这里有一个测试数据,在32位机下,NPTL成功启动100000个线程只用了2秒,而不使用NPTL将需要大约15分钟左右的时间。
历史
在内核2.6以前的调度实体都是进程,内核并没有真正支持线程。它是能过一个系统调用clone()来实现的,这个调用创建了一份调用进程
的拷贝,跟fork()不同的是,这份进程拷贝完全共享了调用进程的地址空间。LinuxThread就是通过这个系统调用来提供线程在内核级的支持的
(许多以前的线程实现都完全是在用户态,内核根本不知道线程的存在)。非常不幸的是,这种方法有相当多的地方没有遵循POSIX标准,特别是在信号处理,
调度,进程间通信原语等方面。
很显然,为了改进LinuxThread必须得到内核的支持,并且需要重写线程库。为了实现这个需求,开始有两个相互竞争的项目:IBM启动的 NGTP(Next Generation POSIX Threads)项目,以及Redhat公司的NPTL。在2003年的年中,IBM放弃了NGTP,也就是大约那时,Redhat发布了最初的 NPTL。
NPTL最开始在redhat linux 9里发布,现在从RHEL3起内核2.6起都支持NPTL,并且完全成了GNU C库的一部分。
设计
NPTL使用了跟LinuxThread相同的办法,在内核里面线程仍然被当作是一个进程,并且仍然使用了clone()系统调用(在NPTL库里调用)。但是,NPTL需要内核级的特殊支持来实现,比如需要挂起然后再唤醒线程的线程同步原语futex.
NPTL也是一个1*1的线程库,就是说,当你使用pthread_create()调用创建一个线程后,在内核里就相应创建了一个调度实体,在linux里就是一个新进程,这个方法最大可能的简化了线程的实现。
除NPTL的1*1模型外还有一个m*n模型,通常这种模型的用户线程数会比内核的调度实体多。在这种实现里,线程库本身必须去处理可能存在的调 度,这样在线程库内部的上下文切换通常都会相当的快,因为它避免了系统调用转到内核态。然而这种模型增加了线程实现的复杂性,并可能出现诸如优先级反转的 问题,此外,用户态的调度如何跟内核态的调度进行协调也是很难让人满意。
对于pthread的更多理解可以参考:http://archive.cnblogs.com/a/1930707/
发表评论
-
Raft
2018-07-12 14:20 734前言 上篇文章说解决问题要分而治之,先把分片的问题解决了再 ... -
java uuid
2017-09-14 18:18 555在java中产生uuid的方式是使用java.util.UU ... -
JAVA 编码规范
2017-09-06 11:34 406https://google.github.io/style ... -
mac 入门
2015-12-01 16:28 622http://foocoder.com/blog/wo-zai ... -
java 反编译工具gad
2014-05-09 12:04 963java 反编译工具gad,备个份。 -
java 代码大全(code book)
2014-04-29 10:59 1060参考这里: http://www.java2s.com/C ... -
SQL语法解析器JSQLParser
2014-02-09 19:53 2138SQL 语法解释器jsqlparser 是用java ... -
BufferedInputStream 深入研究。
2013-11-19 13:26 14181. BufferedInputStream的基本原理 ... -
java 启动脚本
2013-08-22 19:08 976java 启动脚本 #!/bin/bash cmd=&q ... -
CRLF escape
2013-08-06 17:51 1192最近需要对用户输入的CRLF即(\r\n)做escape, ... -
安全的自增类
2013-07-22 18:16 982java中一个计数器如果超过MAX_VALUE再自增会如何? ... -
solr日志被block的问题
2013-05-23 16:48 1255"catalina-exec-22386" ... -
beanMapper
2013-01-13 22:43 885实在被一堆get,set搞烦了,周末写了一个beanMappe ... -
java instanceof ,isInstance(),isAssignableFrom之前的差异
2013-01-06 11:00 958public class ItemQuery { ... -
通过gzip对字符串压缩
2012-12-22 18:10 3102通过GZIPOutputStream,GZIPInputStr ... -
关于URL编码
2012-12-21 14:18 1102一、问题的由来 URL就是网址,只要上网,就一定会用到。 ... -
spring的FactoryBean机制
2012-11-20 16:18 1221spring可以通过的FactoryBean的形式把一个Fac ... -
HashMap cpu占用 100%
2012-11-10 22:22 1805今天在重现出HashMap cpu占用100%了,只 ... -
文字扫描工具--java.util.Scanner
2012-11-10 14:33 1092A simple text scanner which c ... -
一个隐形的java int溢出
2012-11-06 22:17 1103故事的背景: 笔者最近在做一个类SNS的项目, ...
相关推荐
### Java分布式应用学习笔记03:JVM对线程的资源同步和交互机制 在深入探讨Java虚拟机(JVM)如何处理线程间的资源同步与交互机制之前,我们先来明确几个关键概念:线程、多线程、同步、并发以及它们在Java中的实现...
在探究JVM线程状态以及Thread.sleep的实现原理时,我们首先需要了解Java线程与操作系统线程之间的关系。在Java虚拟机(JVM)中,每个线程通常都是以一对一的关系映射到操作系统线程上的。然而,尽管两者在实现上是...
本文将深入探讨“WAS性能调优对jvm、线程数、ORB大小的配置”这一主题。 首先,我们要理解JVM(Java Virtual Machine)在WAS中的作用。JVM是Java程序运行的平台,它的性能直接影响到应用的响应时间和资源利用率。在...
HotSpot虚拟机上,方法区常被实现为永久代(PermGen),但随着JDK 1.8的推出,永久代被元空间(Metaspace)取代。 - **运行时常量池(Runtime Constant Pool)**:是方法区的一部分,存放编译期生成的各种字面量和...
为了确保应用程序高效稳定地运行,开发者需要对JVM进行监控,了解其内部状态,如内存使用、线程活动等。本文将探讨如何在Windows环境下通过简单的命令行工具来监控JVM实例的数量,以及如何进行线程测试,特别是在...
7. **多线程**:JVM内置对多线程的支持,每个线程有自己的程序计数器、本地方法栈和虚拟机栈,共享堆和方法区。 8. **类文件结构**:深入理解`.class`文件的结构,包括魔数、版本号、常量池、字段表、方法表、属性...
总结来说,JVM线程分析主要涉及线程的状态管理,包括对Runnable、Wait on condition、Waiting for monitor entry和in Object.wait()的理解,以及如何利用Monitor进行线程同步。掌握这些知识对于理解和优化Java应用的...
本文将深入探讨Java的核心知识,包括JVM(Java虚拟机)、线程、集合、数据库、算法以及负载均衡等多个方面。 首先,让我们从Java虚拟机(JVM)开始。JVM是Java程序运行的基石,它负责解析字节码并执行。理解JVM的...
本资料集合旨在深入探讨JVM线程的相关知识。 首先,我们来看《Concurrent Programming in Java》这本书。这本书详细介绍了Java中的并发编程,包括JVM线程的创建、管理和同步。其中,线程的生命周期(新建、就绪、...
这有助于深入理解JVM的生命周期管理、异常处理、多线程等复杂概念。 五、优化与进阶 掌握JVM的工作原理后,开发者可以进行更高级的调优,如调整JVM参数以优化内存分配、提高垃圾收集效率等。此外,还可以探索JVM的...
《OpenJDK中的JVM Hotspot实现源码解析》 在Java世界中,JVM(Java Virtual Machine)是运行Java程序的关键组件,它负责将字节码解释执行或即时编译为机器码,使得Java具备跨平台的能力。Hotspot是Oracle JDK和...
在Java虚拟机(JVM)中,线程分为两类:用户线程(User Thread)和守护线程(Daemon Thread)。这两类线程的主要区别在于它们的生命周期与JVM的关系。 1. **用户线程**:用户线程是应用程序中常见的线程类型,它们...
总的来说,Java JVM线程调优需要综合考虑线程栈大小、锁优化策略以及并发同步方法,以适应不同的应用场景。理解这些概念并根据实际情况调整参数,可以显著提升多线程程序的性能。在进行调优时,应结合监控工具分析...
《HotSpot线程实现——线程创建》 在Java编程中,线程是我们处理并发和多任务的基础。本文将深入探讨HotSpot虚拟机中线程的实现,主要关注线程的创建过程。我们使用的JDK版本为1.7。请注意,本文不会涉及Java线程的...
JNI的使用往往涉及到对JVM内部机制的了解,比如如何在本地代码中操作Java对象,管理Java的堆内存,以及处理线程同步问题。 "www.pudn.com.txt"这个文件可能是从网站www.pudn.com下载的资源说明或者示例代码的引用。...
Java虚拟机(JVM)是Java程序运行的基础,它提供了执行字节码...在面试中,理解JVM的工作原理、内存管理、垃圾回收机制以及多线程的实现与优化,不仅能展示出对Java底层机制的掌握,也是解决问题和提升系统性能的关键。
Java内存模型(JMM)规定了线程对共享变量的可见性和有序性,它通过主内存和工作内存的概念来实现多线程之间的协作。 3. JVM调优:JVM调优通常指对JVM进行配置,优化性能以应对特定的应用需求。常见的调优手段包括...
### Java中JVM原理与实现 #### 一、引言 Java虚拟机(JVM)作为Java语言的基础支撑,是确保Java程序能够在不同平台上顺畅运行的关键技术。本文将深入探讨JVM的工作原理及其核心组成部分,包括类加载器、运行时数据区...
6. 多线程:JVM支持多线程并发执行,每个线程都有自己的程序计数器和虚拟机栈。 7. 安全管理:JVM执行严格的类型检查和权限控制,确保代码的安全性。 8. 调优工具:如JVisualVM、JConsole等,帮助开发者监控和调整...
Java进阶学习教程中的第13章主要涵盖了JVM(Java虚拟机)和多线程两个核心概念。JVM是Java程序运行的基础,它负责解释执行字节码文件,并提供了Java语言的跨平台特性。Java程序通过JVM与操作系统交互,使得程序可以...