Java语言的关键字,可用来给对象和方法或者代码块加锁。
1、当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这个段代码。
2、当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
3、当一个线程访问object的一个加锁代码块时,另一个线程仍然可以访问该object中的非加锁代码块。
先看代码
错误用法
package cn.itcast.heima;
public class TraditionalThreadSynchronized {
public static void main(String[] args) {
// TODO Auto-generated method stub
new TraditionalThreadSynchronized().init();//静态方法中不能new内部类的实例对象
}
private void init(){
final Outputer outputer = new Outputer();
new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
outputer.output("ddddddddddddddd");
}
}
}).start();
new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
outputer.output("hhhhhhhhh");
}
}
}).start();
}
class Outputer{
public void output(String name){
int len = name.length();
synchronized (name) { //起不到互斥效果
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}
}
public class TraditionalThreadSynchronized {
public static void main(String[] args) {
// TODO Auto-generated method stub
new TraditionalThreadSynchronized().init();//静态方法中不能new内部类的实例对象
}
private void init(){
final Outputer outputer = new Outputer();
new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
outputer.output("ddddddddddddddd");
}
}
}).start();
new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
outputer.output("hhhhhhhhh");
}
}
}).start();
}
class Outputer{
public void output(String name){
int len = name.length();
synchronized (name) { //起不到互斥效果
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}
}
}
这种用法起不到互斥的效果
如果把内部类改成如
class Outputer{
String xx="";
public void output(String name){
int len = name.length();
synchronized (xx) { //因为锁是对output对象锁,起到互斥效果
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}
}
public void output(String name){
int len = name.length();
synchronized (xx) { //因为锁是对output对象锁,起到互斥效果
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}
}
起到效果,但不能保证不出错
正确的使用方法
static class Outputer{
public void output(String name){
int len = name.length(); //有互斥效果
synchronized(Outputer.class){
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}
public synchronized void output2(String name){
int len = name.length(); //用的是this对象
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
public static synchronized void output3(String name){
int len = name.length(); //有互斥效果
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}
public void output(String name){
int len = name.length(); //有互斥效果
synchronized(Outputer.class){
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}
public synchronized void output2(String name){
int len = name.length(); //用的是this对象
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
public static synchronized void output3(String name){
int len = name.length(); //有互斥效果
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}
output3()和output(),因为output三是字节码对象,output()也传入字节码对象,而output2是this对象,所以output2和output与output3并不互斥