当前位置:首页 » 操作系统 » synchronized源码

synchronized源码

发布时间: 2022-06-16 11:58:10

java中使用了synchronized还会出现重复数据

程序还没试,不过一看 if (Thread.currentThread().getName() == "Thread-1") { 这样的语句,就知道有问题了

第2个,synchronized (aa) {是不同的实例的,加synchronized 有什么用呢

㈡ 怎么阅读spring源码

从HttpServletBean的init()进入,再到initWebApplicationContext(),再到refresh(),再到refreshBeanFactory(),再到finishRefresh(),直到服务器启动成功。不知道读了多少遍,
但是源码的东西实在的太多了,想要完全读懂,完全理清头绪,还差很远啊。所以我只重点关注了两块内容,就是bean的定位加载解析注册、bean的实例化两大块内容,其他地方稍作了解,没有太过深入。
整个容器的启动流程,都在AbstractApplicationContext的refresh()的模板方法中了。

复制代码
1 public void refresh() throws BeansException, IllegalStateException {
2 synchronized (this.startupShutdownMonitor) {
3 // Prepare this context for refreshing.
4 prepareRefresh();
5
6 // Tell the subclass to refresh the internal bean factory.
7 beanFactory = obtainFreshBeanFactory();
8
9 // Prepare the bean factory for use in this context.
10 prepareBeanFactory(beanFactory);
11
12 try {
13 // Allows post-processing of the bean factory in context subclasses.
14 postProcessBeanFactory(beanFactory);
15
16 // Invoke factory processors registered as beans in the context.
17 (beanFactory);
18
19 // Register bean processors that intercept bean creation.
20 registerBeanPostProcessors(beanFactory);
21
22 // Initialize message source for this context.
23 initMessageSource();
24
25 // Initialize event multicaster for this context.
26 ();
27
28 // Initialize other special beans in specific context subclasses.
29 onRefresh();
30
31 // Check for listener beans and register them.
32 registerListeners();
33
34 // Instantiate all remaining (non-lazy-init) singletons.
35 (beanFactory);
36
37 // Last step: publish corresponding event.
38 finishRefresh();
39 }
40
41 catch (BeansException ex) {
42 // Destroy already created singletons to avoid dangling resources.
43 destroyBeans();
44
45 // Reset 'active' flag.
46 cancelRefresh(ex);
47
48 // Propagate exception to caller.
49 throw ex;
50 }
51 }
52 }

其实,我并没有上来就看源码,而是先从看书开始,稍微了解,知道了一些关键点,关键流程,自己产生了一堆疑问,然后带着疑问去读源码,读着读着,发现有些疑问就这么解决了。

㈢ arrayblockingqueue为什么使用了lock而没有使用synchronized

ArrayBlockingQueue 是JDK1.5才加进来的类,在JDK1.5 ReentrantLock 的应能远远好于Synchronized,不过在1.6以后,Synchronized 已经进行了优化,二者的性能已经差不了多少了。而且ReentrantLock支持Condition 可以实现特定唤醒操作,Synchronized 要么唤醒一个或者所有都唤醒,这个特性对阻塞队列的性能影响很大。

㈣ java源代码分析 实在是不太会,求高手教教我。

packagetest2;

importjava.io.BufferedReader;
importjava.io.File;
importjava.io.FileInputStream;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.InputStream;
importjava.io.InputStreamReader;
importjava.util.HashMap;
importjava.util.Map;
importjava.util.Set;

publicclassJavaCodeAnalyzer{
publicstaticvoidanalyze(Filefile)throwsIOException{
//FileOutputStreamfos=newFileOutputStream("F;"+File.separator+"result.txt");
if(!(file.getName().endsWith(".txt")||file.getName().endsWith(".java"))){
System.out.println("输入的分析文件格式不对!");
}
InputStreamis=newFileInputStream(file);
BufferedReaderbr=newBufferedReader(newInputStreamReader(is));
Stringtemp;
intcount=0;
intcountSpace=0;
intcountCode=0;
intcountDesc=0;
Map<String,Integer>map=getKeyWords();
while((temp=br.readLine())!=null){
countKeys(temp,map);
count++;
if(temp.trim().equals("")){
countSpace++;
}elseif(temp.trim().startsWith("/*")||temp.trim().startsWith("//")){
countDesc++;
}else{
countCode++;
}
}
System.out.printf("代码行数:"+countCode+"占总行数的%4.2f ",(double)countCode/count);
System.out.printf("空行数:"+countSpace+"占总行数的%4.2f ",(double)countSpace/count);
System.out.printf("注释行数:"+countDesc+"占总行数的%4.2f ",(double)countDesc/count);
System.out.println("总行数:"+count);
System.out.println("出现最多的5个关键字是:");
System.out.println("");
System.out.println("");
System.out.println("");
System.out.println("");
System.out.println("");
}
publicstaticvoidmain(String[]args){
getKeyWords();
Filefile=newFile("F://Test.java");
try{
analyze(file);
}catch(IOExceptione){
//TODO自动生成catch块
e.printStackTrace();
}
}
publicstaticMap<String,Integer>getKeyWords(){
Map<String,Integer>map=newHashMap<String,Integer>();
String[]keywords={"abstract","assert","boolean","break","byte","case","catch","char","class","continue","default","do","double","else","enum","extends","final","finally","float","for","if","implements","import","instanceof","int","interface","long","native","new","package","private","protected","public","return","strictfp","short","static","super","switch","synchronized","this","throw","throws","transient","try","void","volatile","while","goto","const"};
for(Strings:keywords){
map.put(s,0);
}
returnmap;
}
publicstaticvoidcountKeys(Strings,Map<String,Integer>map){
Set<String>keys=map.keySet();
for(Stringss:keys){
if(s.indexOf(ss)!=-1){
map.put(ss,map.get(ss)+1);
}
}
}
}

上班没啥时间了,还有点没写完,你在想想。

㈤ jave语言的string字符串有哪些特点

以主流的 JDK 版本 1.8 来说,String 内部实际存储结构为 char 数组,源码如下:

publicfinalclassString
implementsjava.io.Serializable,Comparable<String>,CharSequence{
//用于存储字符串的值privatefinalcharvalue[];
//缓存字符串的hashcodeprivateinthash;//Defaultto0
//......其他内容}

String源码中包含下面几个重要的方法。

1. 多构造方法

String 字符串有以下 4 个重要的构造方法:

//String为参数的构造方法publicString(Stringoriginal){
this.value=original.value;
this.hash=original.hash;
}//char[]为参数构造方法publicString(charvalue[]){
this.value=Arrays.Of(value,value.length);
}//StringBuffer为参数的构造方法publicString(StringBufferbuffer){
synchronized(buffer){
this.value=Arrays.Of(buffer.getValue(),buffer.length());
}
}//StringBuilder为参数的构造方法publicString(StringBuilderbuilder){
this.value=Arrays.Of(builder.getValue(),builder.length());
}

其中,比较容易被我们忽略的是以 StringBuffer 和 StringBuilder 为参数的构造函数,因为这三种数据类型,我们通常都是单独使用的,所以这个小细节我们需要特别留意一下。

2. equals() 比较两个字符串是否相等,源码如下:

publicbooleanequals(ObjectanObject){
//对象引用相同直接返回trueif(this==anObject){
returntrue;
}
//判断需要对比的值是否为String类型,如果不是则直接返回falseif(anObjectinstanceofString){
StringanotherString=(String)anObject;
intn=value.length;
if(n==anotherString.value.length){
//把两个字符串都转换为char数组对比charv1[]=value;
charv2[]=anotherString.value;
inti=0;
//循环比对两个字符串的每一个字符while(n--!=0){
//如果其中有一个字符不相等就truefalse,否则继续对比if(v1[i]!=v2[i])
returnfalse;
i++;
}
returntrue;
}
}
returnfalse;
}

String 类型重写了 Object 中的 equals() 方法,equals() 方法需要传递一个 Object 类型的参数值,在比较时会先通过 instanceof 判断是否为 String 类型,如果不是则会直接返回 false,instanceof 的使用如下:

ObjectoString="123";
ObjectoInt=123;
System.out.println(oStringinstanceofString);//返回trueSystem.out.println(oIntinstanceofString);//返回false

当判断参数为 String类型之后,会循环对比两个字符串中的每一个字符,当所有字符都相等时返回true,否则则返回 false。

还有一个和equals()比较类似的方法 equalsIgnoreCase(),它是用于忽略字符串的大小写之后进行字符串对比。

3. compareTo() 比较两个字符串

compareTo()方法用于比较两个字符串,返回的结果为int类型的值,源码如下:

publicintcompareTo(StringanotherString){
intlen1=value.length;
intlen2=anotherString.value.length;
//获取到两个字符串长度最短的那个int值intlim=Math.min(len1,len2);
charv1[]=value;
charv2[]=anotherString.value;
intk=0;
//对比每一个字符while(k<lim){
charc1=v1[k];
charc2=v2[k];
if(c1!=c2){
//有字符不相等就返回差值returnc1-c2;
}
k++;
}
returnlen1-len2;
}

从源码中可以看出,compareTo()方法会循环对比所有的字符,当两个字符串中有任意一个字符不相同时,则 returnchar1-char2。比如,两个字符串分别存储的是 1和 2,返回的值是 -1;如果存储的是 1和 1,则返回的值是 0 ,如果存储的是 2和 1,则返回的值是 1。

还有一个和compareTo()比较类似的方法 compareToIgnoreCase(),用于忽略大小写后比较两个字符串。

可以看出compareTo()方法和equals()方法都是用于比较两个字符串的,但它们有两点不同:

equals()可以接收一个 Object类型的参数,而 compareTo()只能接收一个String类型的参数;
equals()返回值为Boolean,而compareTo()的返回值则为int。
它们都可以用于两个字符串的比较,当equals()方法返回true时,或者是compareTo()方法返回 0时,则表示两个字符串完全相同。

4.其他重要方法

indexOf():查询字符串首次出现的下标位置
lastIndexOf():查询字符串最后出现的下标位置
contains():查询字符串中是否包含另一个字符串
toLowerCase():把字符串全部转换成小写
toUpperCase():把字符串全部转换成大写
length():查询字符串的长度
trim():去掉字符串首尾空格
replace():替换字符串中的某些字符
split():把字符串分割并返回字符串数组
join():把字符串数组转为字符串

知识扩展

1.== 和equals的区别

== 对于基本数据类型来说,是用于比较 “值”是否相等的;而对于引用类型来说,是用于比较引用地址是否相同的。

查看源码我们可以知道 Object 中也有equals() 方法,源码如下:

publicbooleanequals(Objectobj){
return(this==obj);
}

可以看出,Object 中的 equals() 方法其实就是 ==,而 String 重写了 equals() 方法把它修改成比较两个字符串的值是否相等。

publicbooleanequals(ObjectanObject){
//对象引用相同直接返回trueif(this==anObject){
returntrue;
}
//判断需要对比的值是否为String类型,如果不是则直接返回falseif(anObjectinstanceofString){
StringanotherString=(String)anObject;
intn=value.length;
if(n==anotherString.value.length){
//把两个字符串都转换为char数组对比charv1[]=value;
charv2[]=anotherString.value;
inti=0;
//循环比对两个字符串的每一个字符while(n--!=0){
//如果其中有一个字符不相等就truefalse,否则继续对比if(v1[i]!=v2[i])
returnfalse;
i++;
}
returntrue;
}
}
returnfalse;
}

2.final修饰的好处

从String类的源码我们可以看出String是被final修饰的不可继承类,源码如下:

publicfinalclassString implementsjava.io.Serializable,Comparable<String>,CharSequence{//......}

那这样设计有什么好处呢?他会更倾向于使用 final,因为它能够缓存结果,当你在传参时不需要考虑谁会修改它的值;如果是可变类的话,则有可能需要重新拷贝出来一个新值进行传参,这样在性能上就会有一定的损失。

String 类设计成不可变的另一个原因是安全,当你在调用其他方法时,比如调用一些系统级操作指令之前,可能会有一系列校验,如果是可变类的话,可能在你校验过后,它的内部的值又被改变了,这样有可能会引起严重的系统崩溃问题,这是迫使 String 类设计成不可变类的一个重要原因。

总结来说,使用 final 修饰的第一个好处是安全;第二个好处是高效,以 JVM 中的字符串常量池来举例,如下两个变量:

Strings1="java";
Strings2="java";

只有字符串是不可变时,我们才能实现字符串常量池,字符串常量池可以为我们缓存字符串,提高程序的运行效率,如下图所示:

除此之外编译器还会对String字符串做一些优化,例如以下代码:

Strings1="Ja"+"va";
Strings2="Java";
System.out.println(s1==s2);

虽然s1拼接了多个字符串,但对比的结果却是true,我们使用反编译工具,看到的结果如下:

Compiledfrom"StringExample.java"publicclasscom.lagou.interview.StringExample{
publiccom.lagou.interview.StringExample();
Code:
0:aload_0
1:invokespecial#1//Methodjava/lang/Object."<init>":()V4:returnLineNumberTable:
line3:0publicstaticvoidmain(java.lang.String[]);
Code:
0:ldc#2//StringJava2:astore_1
3:ldc#2//StringJava5:astore_2
6:getstatic#3//Fieldjava/lang/System.out:Ljava/io/PrintStream;9:aload_1
10:aload_2
11:if_acmpne1814:iconst_1
15:goto1918:iconst_0
19:invokevirtual#4//Methodjava/io/PrintStream.println:(Z)V22:returnLineNumberTable:
line5:0line6:3line7:6line8:22}

从编译代码 #2 可以看出,代码 "Ja"+"va" 被直接编译成了 "Java" ,因此 s1==s2 的结果才是 true,这就是编译器对字符串优化的结果。

㈥ Java中多线程,synchronized,与 AtomicInteger的问题

通过AtomicInteger来操作 是线程安全的 ,而且性能貌似远超 用synchronized的方法
因此不用加synchronized。确实是资源的浪费。

㈦ spring源码里的一个问题在在注册bean的时候为什么要在synchronized锁定俩次

因为addSingleton方法可是在别的地方调用,如果不加同步,那么就不会同步了。

㈧ 求:用JAVA语言编写的银行家算法的源代码

import java.util.*;

class ThreadTest {
static int type = 4, num = 10; //定义资源数目和线程数目
static int[] resource = new int[type]; //系统资源总数
//static int[] Resource = new int[type]; //副本
static Random rand = new Random();
static Bank[] bank = new Bank[num]; //线程组
Bank temp = new Bank();

public void init() {
//初始化组中每个线程,随机填充系统资源总数
for(int i = 0; i < type; i++)
resource[i] = rand.nextInt(10) + 80;
System.out.print("Resource:");
for(int i = 0; i < type; i++)
System.out.print(" " + resource[i]);
System.out.println("");
for(int i = 0; i < bank.length; i++)
bank[i] = new Bank("#" + i);
}
public ThreadTest4() {
init();
}

class Bank extends Thread {
//银行家算法避免死锁
public int[]
max = new int[type], //总共需求量
need = new int[type], //尚需资源量
allocation = new int[type]; //已分配量
private int[]
request = new int[type], //申请资源量
Resource = new int[type]; //资源副本
private boolean isFinish = false; //线程是否完成
int[][] table = new int[bank.length][type*4]; //二维资源分配表

private void init() {
// 随机填充总共、尚需、已分配量
synchronized(resource) {
for(int i = 0; i < type; i++) {
max[i] = rand.nextInt(5) + 10;
need[i] = rand.nextInt(10);
allocation[i] = max[i] - need[i];
resource[i] -= allocation[i]; //从系统资源中减去已分配的
}
printer();
for(int i = 0; i < type; i++) {
if(resource[i] < 0) {
//若出现已分配量超出系统资源总数的错误则退出
System.out.println("The summation of Threads' allocations is out of range!");
System.exit(1);
}
}
}
}

public Bank(String s) {
setName(s);
init();
start();
}
public Bank() {
//none
}

public void run() {
try {
sleep(rand.nextInt(2000));
}
catch(InterruptedException e) {
throw new RuntimeException(e);
}
while(true) {
//程序没有完成时一直不断申请资源
if(askFor() == false) {
try {
sleep(1000);
}
catch(InterruptedException e) {
throw new RuntimeException(e);
}
}
else
tryRequest();
if(noNeed() == true)
break;
}
//休眠一段时间模拟程序运行
try {
sleep(1000);
}
catch(InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(getName() + " finish!");
synchronized(resource) {
//运行结束释放占有资源
for(int i = 0; i < type; i++) {
resource[i] += allocation[i];
need[i] = allocation[i] = max[i] = 0;
}
}
}

private void printer() {
//打印当前资源信息
System.out.print(getName() + " Max:");
for(int i = 0; i < type; i++)
System.out.print(" " + max[i]);
System.out.print(" Allocation:");
for(int i = 0; i < type; i++)
System.out.print(" " + allocation[i]);
System.out.print(" Need:");
for(int i = 0; i < type; i++)
System.out.print(" " + need[i]);
System.out.print(" Available:");
for(int i = 0; i < type; i++)
System.out.print(" " + resource[i]);
System.out.println("");
}
private boolean askFor() {
//随机产生申请资源量并检测是否超标
boolean canAsk = false;
for(int i = 0; i < type; i++) {
request[i] = rand.nextInt(20);
//防止申请量超过所需量
if(request[i] > need[i])
request[i] = need[i];
}
for(int i = 0; i < type; i++) //防止随机申请资源全为0
if(request[i] > 0)
canAsk = true;
synchronized(resource) {
//锁住可供资源检查是否超标
for(int i = 0; i < type; i++) {
if(request[i] > resource[i])
//如果申请资源超过可供资源则等待一段时间后重新申请
return false;
}
}
return canAsk;
}
private void tryRequest() {
//创建副本尝试分配请求
synchronized(resource) {
for(int i = 0; i < type; i++)
//依然要防止请求量超出范围
if(request[i] > resource[i])
return;
for(int i = 0; i < type; i++) {
//复制资源量并减去需求量到一个副本上
Resource[i] = resource[i];
Resource[i] -= request[i];
}
System.out.print(getName() + " ask for:");
for(int i = 0; i < type; i++)
System.out.print(" " + request[i]);
System.out.println("");
if(checkSafe() == true) {
//如果检查安全则将副本值赋给资源量并修改占有量和需求量
for(int i = 0; i < type; i++) {
resource[i] = Resource[i];
allocation[i] += request[i];
need[i] -= request[i];
}
System.out.println(getName() + " request succeed!");
}
else
System.out.println(getName() + " request fail!");
}
}
private boolean checkSafe() {
//银行家算法检查安全性
synchronized(bank) {
//将线程资源信息放入二维资源分配表检查安全性,0~type可用资源/type~type*2所需资源/type*2~type*3占有资源/type*3~-1可用+占用资源
for(int i = 0; i < bank.length; i++) {
for(int j = type; j < type*2; j++) {
table[i][j] = bank[i].need[j%type];
}
for(int j = type*2; j < type*3; j++) {
table[i][j] = bank[i].allocation[j%type];
}
}
//冒泡排序按需求资源从小到大排
for(int i = 0; i < bank.length; i++) {
for(int j = i; j < bank.length-1; j++) {
sort(j, 4);
}
}
//进行此时刻的安全性检查
for(int i = 0; i < type; i++) {
table[0][i] = Resource[i];
table[0][i+type*3] = table[0][i] + table[0][i+type*2];
if(table[0][i+type*3] < table[1][i+type])
return false;
}
for(int j = 1; j < bank.length-1; j++) {
for(int k = 0; k < type; k++) {
table[j][k] = table[j-1][k+type*3];
table[j][k+type*3] = table[j][k] + table[j][k+type*2];
if(table[j][k+type*3] < table[j+1][k+type])
return false;
}
}
}
return true;
}
private void sort(int j, int k) {
//递归冒泡排序
int tempNum;
if(table[j][k] > table[j+1][k]) {
for(int i = type; i < type*2; i++) {
tempNum = table[j][i];
table[j][i] = table[j+1][i];
table[j+1][i] = tempNum;
}
/*temp = bank[j];
bank[j] = bank[j+1];
bank[j+1] = temp;*/
}
else if(table[j][k] == table[j+1][k] && k < type*2) //此资源量相同时递归下一个资源量排序并且防止超出范围
sort(j, k+1);
}
private boolean noNeed() {
//是否还需要资源
boolean finish = true;
for(int i = 0; i < type; i++) {
if(need[i] != 0) {
finish = false;
break;
}
}
return finish;
}
}

public static void main(String[] args) {
ThreadTest t = new ThreadTest();
//后台线程,设定程序运行多长时间后自动结束
new Timeout(30000, "---Stop!!!---");
}
}

热点内容
动态规划01背包算法 发布:2024-11-05 22:17:40 浏览:849
nasm编译器如何安装 发布:2024-11-05 22:01:13 浏览:180
登录密码在微信的哪里 发布:2024-11-05 22:00:29 浏览:739
c防止反编译工具 发布:2024-11-05 21:56:14 浏览:247
安卓虚拟机怎么用 发布:2024-11-05 21:52:48 浏览:344
php时间搜索 发布:2024-11-05 20:58:36 浏览:479
燕山大学编译原理期末考试题 发布:2024-11-05 20:13:54 浏览:528
华为电脑出现临时服务器 发布:2024-11-05 20:05:08 浏览:408
斗战神免费挖矿脚本 发布:2024-11-05 19:53:25 浏览:665
网吧服务器分别是什么 发布:2024-11-05 19:45:32 浏览:392