Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
4
Question by EvilSam · May 25, 2014 at 03:25 PM · debugthreadsmultithreading

Thread-Safety and Debug.Log

I am using multi-threading in unity for some connection issues, i know that unity API is not thread-safe and I'm taking that into consideration.

All examples about threading in unity use the function group Debug.Log..., so i assumed that they are thread-safe, but i need need to know how "safe" are they, and if it was thread-safe, it will have of course some kind of synchronization, so I need to know what kind of synchronization does it have, does it force the calling thread to wait for the next frame or end of the frame? if so, wouldn't that make the calling thread wait for many frames if it had many Debug.Log statements?

Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Numid · Nov 25, 2015 at 04:30 PM 0
Share

Which examples are you talking about?

2 Replies

· Add your reply
  • Sort: 
avatar image
3
Best Answer

Answer by Bunny83 · Nov 25, 2015 at 05:56 PM

Debug.Log (as well as LogError, LogWarning, ...) are afaik the only methods that are actually threadsafe. Making a method thread safe doesn't necessarily mean that one thread always have to wait for another. They just have to wait when they try to access a shared resource at the same time. When running inside the editor, the editor itself (which runs on the main thread) will most likely pull pending entries from a shared buffer into a display buffer. So only for that copy operation the main thread might lock the shared resource. Likewise when another thread uses a Debug.Log it would also lock the buffer to add that message. The lock only lasts as long as the thread is using the shared resource. (More about that at the end.)

At runtime there is nothing in the main thread that actually "reads" the Debug.Log messages. So the only thing that can make a thread to wait when calling Debug.Log is another thread that is currently executing a Debug.Log. Since you shouldn't overuse Debug.Log and at runtime it executes quite fast you shouldn't see much of a wait time. I'm not sure how Unity handles the logfile writing. It might be done once during the gamecycle on the main thread or they might have a seperate thread for that.

It seems that Unity actually treats Debug.Log calls from the main thread differently than those from other threads. That's why we have the events Application.logMessageReceived and Application.logMessageReceivedThreaded. Unfortunately since they turned the callback into an actual event (before we had to call Application.RegisterLogCallback(callback)) it seems they somehow forgot / dropped the documentation of those ^^.

logMessageReceived is executed on the main thread but it only receives messages from Debug.Log calls that has been executed on the main thread. logMessageReceivedThreaded on the other hand will be called for all Debug.Log calls, but from their respective threads, so you have to do any synchronisations yourself if you use that callback.

That's pretty much all i know about Debug.Log at the moment. I haven't done extensive tests with threads and Debug.Log.


Some additional info about locks:

When we talk about syncronisation, a thread usually don't wait for another thread to do something but it might has to wait until another thread has released a lock or has finished completely (joining with the thread).

A usual lock could be divided into 3 parts:

 lock(someObject)  // part1
 {
     // part2
 }
 // part3

part1 will try to aquire a lock for the given object. If another thread currently has a lock active on that object, the thread will wait on this line until the lock is release.

part2 this is the "threadsafe area". Here you can access a shared resource since you can ensure that you are the only one inside that safe area that belongs to the "someObject".

part3 at this point our thread has released the lock and another thread (that might have waited on the lock statement already) now might have taken the lock.

The key for effectiveness is to keep the time a thread holds a lock as short as possible and if possible, avoid aquiring the lock in the first place. This can be done by using a simple volatile flag that a "producer" sets when he has placed data into the buffer. This flag can be read by another thread without using a lock. It can be used to avoid locking an object in a "consumer" thread if there's no new data.

For example this is a bad example of a polling thread:

 while (true)
 {
     lock(lockHandle)
     {
         // check if data available
     }
 }

This is bad because of the ratio between the time inside and outside the lock. Since you do nothing outside the lock the thread will have the lock probably 99% of the time. It's also bad since this thread will run at "maximum speed" and causes the core it runs on to have 99.9% usage, even it does almost nothing. A simple Thread.Sleep would fix that.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image EvilSam · Dec 30, 2015 at 04:17 AM 0
Share

thanks for the reply, i noticed it one month late because i asked the question like 7 months ago.

now i can say that i used it and i didn't see encounter any problems, the goal of my question was to find any official statement about it.

and for the synchronization part, i know that it's bad design and Unity is highly unlikely to be like that, but i've seen some engines unnecessarily lock some resources before the update and not releasing them until the end of rendering.

avatar image
1

Answer by Numid · Nov 27, 2015 at 12:53 PM

 void Start()
 {
   (new Thread(() => {
     new GameObject();
   })).Start();
 }

Raises an exception.

 void Start()
 {
   (new Thread(() => {
     Debug.Log("A message");
   })).Start();
 }

Does not raise any exception.

It might mean that Debug.Log is thread safe. However this feature is not documented. You can not rely on it.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

22 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Multithreaded Input Detection 2 Answers

Instantiating many objects during update lags 1 Answer

Having issues when multithreading and deserializing JSON with JSONUtility 1 Answer

Call long running AI function without tying up game loop? 1 Answer

3D voxel Planet (dual contouring) Job System or Task Parallel Library? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges