DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
View Events Video Library
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Integrating PostgreSQL Databases with ANF: Join this workshop to learn how to create a PostgreSQL server using Instaclustr’s managed service

Mobile Database Essentials: Assess data needs, storage requirements, and more when leveraging databases for cloud and edge applications.

Monitoring and Observability for LLMs: Datadog and Google Cloud discuss how to achieve optimal AI model performance.

Automated Testing: The latest on architecture, TDD, and the benefits of AI and low-code tools.

Related

  • Visualizing Thread-Safe Singletons in Java
  • Double-Checked Locking Design Pattern in Java
  • Java: How Object Reuse Can Reduce Latency and Improve Performance
  • Java: Creating Terabyte Sized Queues with Low-Latency

Trending

  • Best Practices for Writing Clean Java Code
  • Revolutionizing Software Testing
  • Demystifying Enterprise Integration Patterns: Bridging the Gap Between Systems
  • Docker and Kubernetes Transforming Modern Deployment
  1. DZone
  2. Software Design and Architecture
  3. Integration
  4. Don’t deadlock with async and await

Don’t deadlock with async and await

Filip Ekberg user avatar by
Filip Ekberg
·
Apr. 05, 13 · Interview
Like (0)
Save
Tweet
Share
5.29K Views

Join the DZone community and get the full member experience.

Join For Free

Deadlocking is really something you need to avoid and in case you don’t know what a deadlock is here’s a great illustration of a “real life deadlock”:

deadlock

Basically what has happened here is that all the roads are full with cars and all the cars try to cross the road at the same time. Let’s translate this into computer terms; the cars in this case are the threads and the cross-over is the “thing” that handles these threads. In the illustration above all the cars have driven into the cross-over at the same time and they can’t really back up, hence there’s a deadlock and there’s no way to go.

What happens in a computer program when you get a deadlock is that it freezes and there’s no where to go because all paths are occupied or waiting for something to finish. Let’s say that process X waits for process Y and process Y waits for process X and both of these lock up the GUI thread, this means that the application will die. Hence deadlocking is something you want to avoid.

Normally you solve this by introducing locking and semaphores. As discussed in the article linked above (where I got the very nice illustration) a semaphore can be seen as a traffic light which handles how the cross-over is loaded with cars.

A while back I wrote an article called “Avoid shooting yourself in the foot with Tasks and Async”, I suggest that you should always return a Task from your asynchronous methods and you really should. What I am about to tell you below though is what you should avoid when doing this.

When a method is marked as asynchronous and the await-part is reached, the method will “exit” and return the “awaiting Task“, which means it’s not the Task that runs inside the method but in fact a Task that keeps track of the status of the asynchronous operation.

Let’s look at a basic code sample!

Consider that you have the following basic asynchronous method, all it does is that it waits for 2 seconds and then prints something to the debug window:

private async Task RunAsync()
{
    var run = Task.Factory.StartNew(() => {
        Task.Delay(2000);
    });

    await run;

    Debug.WriteLine("Execution done!");
}

Once await is reached, what will happen? A Task will be returned, but which one? Not the one named run! A Task that keeps track on the state machine will be returned.

Now what happens if we call this method on the GUI thread and asks to wait for it to finish? Calling Wait freezes the current thread and since we are on the GUI thread this will freeze the GUI thread, but for how long? When is Wait happy enough to proceed? In fact it will wait for the asynchronous task that handles the state machine to give it a signal that it’s now ready.

However that Task can never be marked as done until the entire method has been completed. Which means that it needs to access the GUI thread again, since we’re back on the calling thread (GUI thread in this case) after await!

This means that all we have to do in order to deadlock is this:

RunAsync().Wait();

I hope that makes sense to you and gives you an insight into what really happens when you use async and await. As with everything: use it wisely and know what it is that you’re doing.

I’d love to hear about your deadlocking stories!


Threading

Opinions expressed by DZone contributors are their own.

Related

  • Visualizing Thread-Safe Singletons in Java
  • Double-Checked Locking Design Pattern in Java
  • Java: How Object Reuse Can Reduce Latency and Improve Performance
  • Java: Creating Terabyte Sized Queues with Low-Latency

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: