从Linux的errno到Java的ThreadLocal

Linux里的errno



在Linux下执行系统调用时,一般会有一个返回值表示成功或失败,但是这个值只说明了成功或失败,却没有说明是如何成功或失败的。

errno就是为了解决这个问题的,系统调用会把错误号设置为errno,我们通过错误号就能知道失败的原因。还可以使用strerror打印出这个错误号对应的字符串说明。老版本的Linux需要加上extern int errno,现在直接引入<errno.h>就行了.

errno示例:

现在的问题来了。假如我有两个线程,代码如下:

errno是一个全局变量,那么假如执行顺序为 1-1,2-1,1-2,2-2,线程1打印出的errno就是线程2的,这就是errno的问题,线程不安全。

但是测试很多次,结果都是正确的。虽然你用这个errno是当作一个全局变量的,但是实际上是个宏。用gcc -E将源代码的宏展开,可以看到,errno被替换成了一个函数。

使用man errno查看对errno的解释,可以看到下面一句话:

errno  is  defined  by  the ISO C standard to be a modifiable lvalue of
       type int, and must not be explicitly declared; errno may  be  a  macro.
       errno  is  thread-local;  setting  it in one thread does not affect its
       value in any other thread.

所以errno并不是一个全局变量,而是一个thread-local,每个线程都有一个。我们可以自己实现一个errno。

自己写一个errno



仅仅演示一下errno的基本原理,使用一个map存放各个线程的errno,而这个map的key就是threadId。系统调用执行完毕后,会将错误码写入此线程对应的errno中。代码中的系统调用是一个假系统调用,some_system_call()。

实际开发中,对于开发者,他实际上是看不到set_errno(),get_errno()这些函数的,他只需要取errno就行了。

Java的ThreadLocal



Java的ThreadLocal和Linux的errno是一样的,只不过errno对开发者来说更简单一点,而且只能取,当作一个变量就行了。

只定义了一个ThreadLocal,但是各个线程里的都不一样。

自己实现一个ThreadLocal



其实ThreadLocal也和上面我自己实现的errno类似,用了一个Map,感兴趣的可以去看一下jdk源码,我写了一个很简陋的MyThreadLocal,Java的ThreadLocal的原理大致就是这样的。直接将上面的代码的ThreadLocal替换成MyThreadLocal就可以运行,当然这个MyThreadLocal太简单,仅仅为了介绍原理。

时间: 2024-12-29 23:20:48

从Linux的errno到Java的ThreadLocal的相关文章

Java之ThreadLocal原理分析

简介 早在JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路.使用这个工具类可以很简洁地编写出优美的多线程程序.当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本.从线程的角度看,目标变量就象是线程的本地变量,这也是类名中“Local”所要表达的意思.所以,在Java中编写线程局部变量

[转] Ubuntu/Linux Mint/Debian 安装 Java 8

本PPA由webupd8制作,支持Ubuntu 12.10, 12.04, 11.10, 11.04, 10.10 和 10.04以及对应的Linux Mint版本,Oracle Java 8包提供JDK8 和 JRE8. sudo add-apt-repository ppa:webupd8team/java sudo apt-get update sudo apt-get install oracle-java8-installer 安装后查看版本: $ java -version java

linux下的shell命令的编写,以及java如何调用linux的shell命令(java如何获取linux上的网卡的ip信息)

程序员都很懒,你懂的! 最近在开发中,需要用到服务器的ip和mac信息.但是服务器是架设在linux系统上的,对于多网口,在获取ip时就产生了很大的问题.下面是在windows系统上,java获取本地ip的方法.贴代码: package com.herman.test; import java.net.InetAddress; /** * @see 获取计算机ip * @author Herman.Xiong * @date 2014年5月16日 09:35:38 */ public class

java concurrency: ThreadLocal及其实现机制

转载:http://shmilyaw-hotmail-com.iteye.com/blog/1703382 ThreadLocal概念 从字面上来理解ThreadLocal,感觉就是相当于线程本地的.我们都知道,每个线程在jvm的虚拟机里都分配有自己独立的空间,线程之间对于本地的空间是相互隔离的.那么ThreadLocal就应该是该线程空间里本地可以访问的数据了.ThreadLocal变量高效地为每个使用它的线程提供单独的线程局部变量值的副本.每个线程只能看到与自己相联系的值,而不知道别的线程可

Linux中如何设置java环境变量

这里介绍Linux下如何设置java环境变量. 工具/原料 Linux java环境变量 方法/步骤 1 查看java的安装路径   查看java执行路径   配置java环境变量   java的安装路径和执行路径   注意这里的JAVA_HOME后面一定要带上bin路径,路径设置完成一定要用 export输出,注意export单词不要写错了   设置环境变量后使用java的v参数测试,还是失败,因为没有执行source命令   环境变量修改后执行source命令,使得配置生效   运行sour

jstack来分析。当linux出现cpu被java程序消耗过高时

我们使用jdk自带的jstack来分析.当linux出现cpu被java程序消耗过高时,以下过程说不定可以帮上你的忙: 1.top查找出哪个进程消耗的cpu高 21125 co_ad2    18   0 1817m 776m 9712 S  3.3  4.9  12:03.24 java                                                                                           5284 co_ad    

深入研究java.lang.ThreadLocal类

深入研究java.lang.ThreadLocal类 一.概述 ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是threadlocalvariable(线程局部变量).也许把它命名为ThreadLocalVar更加合适.线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是Java中一种较为特殊的线程绑定机制,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副

使用linux perf工具生成java程序火焰图

pre.cjk { font-family: "Nimbus Mono L", monospace } p { margin-bottom: 0.1in; line-height: 120% } a:link { } 重要参考文献:www.brendangregg.com/blog/2017-06-30/package-flame-graph.html Java FlameGraph(火焰图)能够非常直观的展示java程序的性能分析结果,方便发现程序热点和进一步调优.本文将展示如何使用

java的ThreadLocal类的用法

java的ThreadLocal类的用法,ThreadLocal是一个支持泛型的类,用在多线程中用于防止并发冲突问题. 例如下面的一个例子,就是用于线程增加1,但是相互不冲突 package com.test.threadlocal; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; class Local { private static ThreadLocal<Integer